Pregunta sobre diseño de PK

02/02/2008 - 14:11 por Luis Flores | Informe spam
Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras del
nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en los
BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de las
identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis

Preguntas similare

Leer las respuestas

#1 Jesús López
02/02/2008 - 15:28 | Informe spam
Bueno pues una solución podría ser la siguiente:


CREATE TABLE Items
(
CodItem char(6) PRIMARY KEY,
ItemPrefix AS LEFT(CodItem, 3),
Secuential AS CONVERT(int, RIGHT(CodItem, 3)),
ItemName varchar(50) NOT NULL
)
GO

CREATE INDEX Items_Prefix_Secuential ON Items(ItemPrefix, Secuential DESC)


ALTER PROCEDURE InsertItem
@ItemName varchar(50),
@CodItem char(6) OUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @ItemPrefix char(3)
SET @ItemPrefix = LEFT(@ItemName, 3)
DECLARE @Secuential int
BEGIN TRANSACTION
EXEC sp_getapplock @ItemPrefix, 'Exclusive'

SELECT TOP(1) @Secuential = Secuential + 1
FROM Items
WHERE ItemPrefix = @ItemPrefix
ORDER BY Secuential DESC

IF @Secuential IS NULL SET @Secuential = 1

SET @CodItem = @ItemPrefix + RIGHT( '00' + CONVERT(varchar(3),
@Secuential), 3)
SET NOCOUNT OFF
INSERT INTO Items VALUES( @CodItem, @ItemName)
SET NOCOUNT ON
EXEC sp_releaseapplock @ItemPrefix
COMMIT
END


Pruebas:

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA uno', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA dos', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA tres', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB uno', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB dos', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB tres', @CodItem OUT
PRINT @CodItem
GO

Saludos:

Jesús López
www.solidq.com



"Luis Flores" escribió en el mensaje
news:
Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras del
nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en los
BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de las
identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis

Respuesta Responder a este mensaje
#2 Alejandro Mesa
02/02/2008 - 17:10 | Informe spam
Luis Flores,

Pudieras tener una tabla de ayuda, donde almacenas el par (prefijo_Item,
ultima_secuencia) donde el prefijo del item es clave primaria. Entonces cada
vez que insertes un item, tomas el valor de la proxima secuencia desde esta
tabla.

USE tempdb
GO

CREATE TABLE dbo.prefijo_item_ultima_seq (
prefijo_item_ultima_seqID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL,
ultima_seq INT NOT NULL DEFAULT(0) CHECK(ultima_seq >= 0),
CONSTRAINT PK_prefijo_item_ultima_seq PRIMARY KEY CLUSTERED
(prefijo_item_ultima_seqID),
CONSTRAINT UQ_prefijo_item_ultima_seq_prefijo_item UNIQUE (prefijo_item)
)
go

CREATE PROCEDURE dbo.usp_TomarUltimaSeq
@prefijo_item CHAR(3),
@seq INT OUTPUT
AS
SET nocount ON

UPDATE dbo.prefijo_item_ultima_seq
SET @seq = ultima_seq = ultima_seq + 1
WHERE prefijo_item = @prefijo_item

RETURN @@error
GO

CREATE TABLE dbo.Item (
ItemID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL REFERENCES
dbo.prefijo_item_ultima_seq(prefijo_item),
seq INT NOT NULL CHECK(seq >= 0),
prefijo_seq AS ISNULL(prefijo_item + RIGHT('000' + LTRIM(seq), 3), ''),
Nombre VARCHAR(50) NOT NULL,
CONSTRAINT PK_Item PRIMARY KEY CLUSTERED (ItemID),
CONSTRAINT UQ_Item_prefijo_item_seq UNIQUE (prefijo_item, seq),
CONSTRAINT CK_Item_Nombre CHECK(Nombre LIKE prefijo_item + '%')
)
go

CREATE PROCEDURE dbo.usp_InsertItem
@Nombre VARCHAR(50)
AS
SET NOCOUNT ON

DECLARE @prefijo CHAR(3)
DECLARE @seq INT

DECLARE @rv INT
DECLARE @rc INT
DECLARE @error INT

SET @prefijo = LEFT(@Nombre, 3)

BEGIN TRANSACTION

EXEC @rv = dbo.usp_TomarUltimaSeq @prefijo, @seq OUTPUT

SET @error = COALESCE(NULLIF(@rv, 0), @@ERROR)

IF @error != 0 OR @seq IS NULL GOTO ErrorHandler

INSERT INTO dbo.Item (prefijo_item, seq, Nombre)
VALUES (@prefijo, @seq, @Nombre)

SELECT @error = @@ERROR, @rc = @@ROWCOUNT

IF @error != 0 OR @rc = 0 GOTO ErrorHandler

COMMIT TRANSACTION

RETURN @@ERROR

ErrorHandler:
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION

RETURN COALESCE(NULLIF(@error, 0), -1)
GO

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('SQL', 0)

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('MS ', 0)
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
GO

DECLARE @rv INT

EXEC @rv = dbo.usp_InsertItem 'SQL Server 7.0'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2000'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2005'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2008'

EXEC @rv = dbo.usp_InsertItem 'MS Office 2003'
EXEC @rv = dbo.usp_InsertItem 'MS Office 2007'
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
SELECT * FROM dbo.Item
GO

DROP PROCEDURE dbo.usp_InsertItem, dbo.usp_TomarUltimaSeq
GO

DROP TABLE dbo.Item, dbo.prefijo_item_ultima_seq
GO

Ahora te comento porque decidi poner el prefijo del item y la secuencia en
columnas separadas. Si deseas hacer este tipo de busquedas:

declare @prefijo char(3)
declare @seq_inicio int, @seq_fin int

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item = @prefijo_Item
and seq between @seq_inicio and @seq_fin

No tendras ningun problema con el esquema usado, pero si en cambio solo
tienes la columna prefijo_item_seq (AAA999), entonces tendras que manipular
la columna en la expresion y no estaras ayudando al optimizador de queries en
la busqueda del plan de ejecucion adecuado.

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item like @prefijo_Item + '%'
and right(seq, 3) between @seq_inicio and @seq_fin

Fijate que la expresion de filtro cambia, sobre todo fijate en la
introduccion de right(seq, 3).

No existe una formula magica en esto de dise~nar una base de datos, asi que
tambien te comento que usar este esquema tiene el inconveniente de que no
podemos llamar al procedimiento que nos devuelve la proxima secuencia a usar
para un determinado prefijo, durante una carga masiva (BULK INSERT).


AMB


"Luis Flores" wrote:

Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras del
nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en los
BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de las
identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis



Respuesta Responder a este mensaje
#3 Luis Flores
02/02/2008 - 17:17 | Informe spam
Gracias.

"Jesús López" escribió en el
mensaje news:
Bueno pues una solución podría ser la siguiente:


CREATE TABLE Items
(
CodItem char(6) PRIMARY KEY,
ItemPrefix AS LEFT(CodItem, 3),
Secuential AS CONVERT(int, RIGHT(CodItem, 3)),
ItemName varchar(50) NOT NULL
)
GO

CREATE INDEX Items_Prefix_Secuential ON Items(ItemPrefix, Secuential DESC)


ALTER PROCEDURE InsertItem
@ItemName varchar(50),
@CodItem char(6) OUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @ItemPrefix char(3)
SET @ItemPrefix = LEFT(@ItemName, 3)
DECLARE @Secuential int
BEGIN TRANSACTION
EXEC sp_getapplock @ItemPrefix, 'Exclusive'

SELECT TOP(1) @Secuential = Secuential + 1
FROM Items
WHERE ItemPrefix = @ItemPrefix
ORDER BY Secuential DESC

IF @Secuential IS NULL SET @Secuential = 1

SET @CodItem = @ItemPrefix + RIGHT( '00' + CONVERT(varchar(3),
@Secuential), 3)
SET NOCOUNT OFF
INSERT INTO Items VALUES( @CodItem, @ItemName)
SET NOCOUNT ON
EXEC sp_releaseapplock @ItemPrefix
COMMIT
END


Pruebas:

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA uno', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA dos', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem 'AAA tres', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB uno', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB dos', @CodItem OUT
PRINT @CodItem
GO

DECLARE @CodItem char(6)
EXEC InsertItem BBB tres', @CodItem OUT
PRINT @CodItem
GO

Saludos:

Jesús López
www.solidq.com



"Luis Flores" escribió en el mensaje
news:
Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras
del nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en
los BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de
las identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis





Respuesta Responder a este mensaje
#4 Luis Flores
02/02/2008 - 17:19 | Informe spam
Gracias.
Creo que es la mejor solución que puedo implementar y te agradezco los
detalles y la explicacion.

Saludos
Luis

"Alejandro Mesa" escribió en el
mensaje news:
Luis Flores,

Pudieras tener una tabla de ayuda, donde almacenas el par (prefijo_Item,
ultima_secuencia) donde el prefijo del item es clave primaria. Entonces
cada
vez que insertes un item, tomas el valor de la proxima secuencia desde
esta
tabla.

USE tempdb
GO

CREATE TABLE dbo.prefijo_item_ultima_seq (
prefijo_item_ultima_seqID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL,
ultima_seq INT NOT NULL DEFAULT(0) CHECK(ultima_seq >= 0),
CONSTRAINT PK_prefijo_item_ultima_seq PRIMARY KEY CLUSTERED
(prefijo_item_ultima_seqID),
CONSTRAINT UQ_prefijo_item_ultima_seq_prefijo_item UNIQUE (prefijo_item)
)
go

CREATE PROCEDURE dbo.usp_TomarUltimaSeq
@prefijo_item CHAR(3),
@seq INT OUTPUT
AS
SET nocount ON

UPDATE dbo.prefijo_item_ultima_seq
SET @seq = ultima_seq = ultima_seq + 1
WHERE prefijo_item = @prefijo_item

RETURN @@error
GO

CREATE TABLE dbo.Item (
ItemID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL REFERENCES
dbo.prefijo_item_ultima_seq(prefijo_item),
seq INT NOT NULL CHECK(seq >= 0),
prefijo_seq AS ISNULL(prefijo_item + RIGHT('000' + LTRIM(seq), 3), ''),
Nombre VARCHAR(50) NOT NULL,
CONSTRAINT PK_Item PRIMARY KEY CLUSTERED (ItemID),
CONSTRAINT UQ_Item_prefijo_item_seq UNIQUE (prefijo_item, seq),
CONSTRAINT CK_Item_Nombre CHECK(Nombre LIKE prefijo_item + '%')
)
go

CREATE PROCEDURE dbo.usp_InsertItem
@Nombre VARCHAR(50)
AS
SET NOCOUNT ON

DECLARE @prefijo CHAR(3)
DECLARE @seq INT

DECLARE @rv INT
DECLARE @rc INT
DECLARE @error INT

SET @prefijo = LEFT(@Nombre, 3)

BEGIN TRANSACTION

EXEC @rv = dbo.usp_TomarUltimaSeq @prefijo, @seq OUTPUT

SET @error = COALESCE(NULLIF(@rv, 0), @@ERROR)

IF @error != 0 OR @seq IS NULL GOTO ErrorHandler

INSERT INTO dbo.Item (prefijo_item, seq, Nombre)
VALUES (@prefijo, @seq, @Nombre)

SELECT @error = @@ERROR, @rc = @@ROWCOUNT

IF @error != 0 OR @rc = 0 GOTO ErrorHandler

COMMIT TRANSACTION

RETURN @@ERROR

ErrorHandler:
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION

RETURN COALESCE(NULLIF(@error, 0), -1)
GO

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('SQL', 0)

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('MS ', 0)
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
GO

DECLARE @rv INT

EXEC @rv = dbo.usp_InsertItem 'SQL Server 7.0'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2000'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2005'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2008'

EXEC @rv = dbo.usp_InsertItem 'MS Office 2003'
EXEC @rv = dbo.usp_InsertItem 'MS Office 2007'
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
SELECT * FROM dbo.Item
GO

DROP PROCEDURE dbo.usp_InsertItem, dbo.usp_TomarUltimaSeq
GO

DROP TABLE dbo.Item, dbo.prefijo_item_ultima_seq
GO

Ahora te comento porque decidi poner el prefijo del item y la secuencia en
columnas separadas. Si deseas hacer este tipo de busquedas:

declare @prefijo char(3)
declare @seq_inicio int, @seq_fin int

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item = @prefijo_Item
and seq between @seq_inicio and @seq_fin

No tendras ningun problema con el esquema usado, pero si en cambio solo
tienes la columna prefijo_item_seq (AAA999), entonces tendras que
manipular
la columna en la expresion y no estaras ayudando al optimizador de queries
en
la busqueda del plan de ejecucion adecuado.

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item like @prefijo_Item + '%'
and right(seq, 3) between @seq_inicio and @seq_fin

Fijate que la expresion de filtro cambia, sobre todo fijate en la
introduccion de right(seq, 3).

No existe una formula magica en esto de dise~nar una base de datos, asi
que
tambien te comento que usar este esquema tiene el inconveniente de que no
podemos llamar al procedimiento que nos devuelve la proxima secuencia a
usar
para un determinado prefijo, durante una carga masiva (BULK INSERT).


AMB


"Luis Flores" wrote:

Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras
del
nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en
los
BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de las
identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis



Respuesta Responder a este mensaje
#5 Jesús López
02/02/2008 - 19:00 | Informe spam
¿Por qué dices que es la mejor solución?

La solución de Alejandro tiene un problema: presupone que todos los prefijos
ya están añadidos a la tabla de prefijos. ¿Qué pása si intentas añadir un
item cuyo prefijo no está en la tabla de prefijos? Sencillamente no
funciona. Una primera aproximación a ese problema sería que el procedimiento
usp_TomarUltimaSeq insertara el prefijo en caso de no existir, pero eso
plantea un nuevo problema ¿Qué pasa si dos conexiones intentan insertar un
nuevo item cuyo prefijo no está en la tabla de prefijos? pues que las dos
conexiones intentarán insertar el mismo prefijo, violándose la clave
primaria.

No te creas que cuando yo he propuesto mi solución no he pensado en una
tabla auxiliar de "secuencias" o prefijos como la quieras llamar. He visto
los problemas que planteaba y he pensado que era mejor solución utilizar una
variación de la técnica MAX+1 para secuencias. Además la técnica que yo he
propuesto es más simple, no requiere de tablas auxiliares ni crear
procedimientos auxiliares. También te puedo decir que es eficiente. He
probado de varias formas diferentes de implementarla y he llegado a la
conclusión de que la técnica propuesta es la implementación más eficiente
posible de técnica MAX+1 para secuencias.

Saludos:

Jesús López
www.solidq.com






"Luis Flores" escribió en el mensaje
news:%
Gracias.
Creo que es la mejor solución que puedo implementar y te agradezco los
detalles y la explicacion.

Saludos
Luis

"Alejandro Mesa" escribió en el
mensaje news:
Luis Flores,

Pudieras tener una tabla de ayuda, donde almacenas el par (prefijo_Item,
ultima_secuencia) donde el prefijo del item es clave primaria. Entonces
cada
vez que insertes un item, tomas el valor de la proxima secuencia desde
esta
tabla.

USE tempdb
GO

CREATE TABLE dbo.prefijo_item_ultima_seq (
prefijo_item_ultima_seqID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL,
ultima_seq INT NOT NULL DEFAULT(0) CHECK(ultima_seq >= 0),
CONSTRAINT PK_prefijo_item_ultima_seq PRIMARY KEY CLUSTERED
(prefijo_item_ultima_seqID),
CONSTRAINT UQ_prefijo_item_ultima_seq_prefijo_item UNIQUE (prefijo_item)
)
go

CREATE PROCEDURE dbo.usp_TomarUltimaSeq
@prefijo_item CHAR(3),
@seq INT OUTPUT
AS
SET nocount ON

UPDATE dbo.prefijo_item_ultima_seq
SET @seq = ultima_seq = ultima_seq + 1
WHERE prefijo_item = @prefijo_item

RETURN @@error
GO

CREATE TABLE dbo.Item (
ItemID INT NOT NULL IDENTITY(1, 1),
prefijo_item CHAR(3) NOT NULL REFERENCES
dbo.prefijo_item_ultima_seq(prefijo_item),
seq INT NOT NULL CHECK(seq >= 0),
prefijo_seq AS ISNULL(prefijo_item + RIGHT('000' + LTRIM(seq), 3), ''),
Nombre VARCHAR(50) NOT NULL,
CONSTRAINT PK_Item PRIMARY KEY CLUSTERED (ItemID),
CONSTRAINT UQ_Item_prefijo_item_seq UNIQUE (prefijo_item, seq),
CONSTRAINT CK_Item_Nombre CHECK(Nombre LIKE prefijo_item + '%')
)
go

CREATE PROCEDURE dbo.usp_InsertItem
@Nombre VARCHAR(50)
AS
SET NOCOUNT ON

DECLARE @prefijo CHAR(3)
DECLARE @seq INT

DECLARE @rv INT
DECLARE @rc INT
DECLARE @error INT

SET @prefijo = LEFT(@Nombre, 3)

BEGIN TRANSACTION

EXEC @rv = dbo.usp_TomarUltimaSeq @prefijo, @seq OUTPUT

SET @error = COALESCE(NULLIF(@rv, 0), @@ERROR)

IF @error != 0 OR @seq IS NULL GOTO ErrorHandler

INSERT INTO dbo.Item (prefijo_item, seq, Nombre)
VALUES (@prefijo, @seq, @Nombre)

SELECT @error = @@ERROR, @rc = @@ROWCOUNT

IF @error != 0 OR @rc = 0 GOTO ErrorHandler

COMMIT TRANSACTION

RETURN @@ERROR

ErrorHandler:
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION

RETURN COALESCE(NULLIF(@error, 0), -1)
GO

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('SQL', 0)

INSERT INTO dbo.prefijo_item_ultima_seq (
prefijo_item,
ultima_seq
) VALUES ('MS ', 0)
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
GO

DECLARE @rv INT

EXEC @rv = dbo.usp_InsertItem 'SQL Server 7.0'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2000'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2005'
EXEC @rv = dbo.usp_InsertItem 'SQL Server 2008'

EXEC @rv = dbo.usp_InsertItem 'MS Office 2003'
EXEC @rv = dbo.usp_InsertItem 'MS Office 2007'
GO

SELECT * FROM dbo.prefijo_item_ultima_seq
SELECT * FROM dbo.Item
GO

DROP PROCEDURE dbo.usp_InsertItem, dbo.usp_TomarUltimaSeq
GO

DROP TABLE dbo.Item, dbo.prefijo_item_ultima_seq
GO

Ahora te comento porque decidi poner el prefijo del item y la secuencia
en
columnas separadas. Si deseas hacer este tipo de busquedas:

declare @prefijo char(3)
declare @seq_inicio int, @seq_fin int

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item = @prefijo_Item
and seq between @seq_inicio and @seq_fin

No tendras ningun problema con el esquema usado, pero si en cambio solo
tienes la columna prefijo_item_seq (AAA999), entonces tendras que
manipular
la columna en la expresion y no estaras ayudando al optimizador de
queries en
la busqueda del plan de ejecucion adecuado.

set @prefijo = 'SQL'
set @seq_inicio = 2
set @seq_fin = 3

select
*
from
dbo.Item
where
prefijo_item like @prefijo_Item + '%'
and right(seq, 3) between @seq_inicio and @seq_fin

Fijate que la expresion de filtro cambia, sobre todo fijate en la
introduccion de right(seq, 3).

No existe una formula magica en esto de dise~nar una base de datos, asi
que
tambien te comento que usar este esquema tiene el inconveniente de que no
podemos llamar al procedimiento que nos devuelve la proxima secuencia a
usar
para un determinado prefijo, durante una carga masiva (BULK INSERT).


AMB


"Luis Flores" wrote:

Me piden para una tabla de Items un codigo alfanumerico pero con la
siguiente caracteristica;

AAA999, donde AAA son tres letras correspondientes a las tres primeras
del
nombre del item y 999 es una secuencia.
Ejemplos de codigos: PAP001, PAP002, ALM001, ALM002...

Quieren que el sistema me genere la proxima secuencia. He buscado en
los
BOL como hacer eso en SQL pero no encuentro la manera, solo veo lo de
las
identity.


Alguna ayuda al respecto? Me conformaria incluso con tener el codigo
separado en dos campos, si no hay mas remedio y tener un el consecutivo
autoincrementado, si se puede.

Gracias

Luis









Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida