SQL SERVER | LLAVE PRIMARIA - CAMPO ESTADO

626 views
Skip to first unread message

Aldo Santos

unread,
May 11, 2017, 12:14:23 AM5/11/17
to publice...@googlegroups.com

Hola a todos,

Necesito de su orientación para el siguiente caso:

·         En una tabla tenemos un campo CODIGO como clave primaria (PK) pero en vez usar el comando DELETE –para eliminar el registro-, necesitamos que no se elimine –por contingencia- sino colocarlo como un registro no activo (igual que VFP) para mantener un historial.

·         El problema se origina al momento de crear un registro, borrarlo y volverlo a crear (todo esto con un mismo código) por lógica no lo permitiría, por la clave primaria. Igual problema sucede si colocamos el campo ESTADO (0=INACTIVO – 1=ACTIVO) como parte de la clave primaria.

 

Una alternativa dada es crear un campo ALEATORIO de 10 caracteres y que se llene con datos aleatorios (similar al GUID), crear la llave primaria por ese campo y crear el campo CODIGO como tipo INDICE.

 

Bajo esta premisa, como podemos hacer para obtener el resutado que deseamos. La alternativa de solución es factible? Bajo ese diseño de base de datos, tiene logica?

 

Espero que se me pueda entender y agradezco su tiempo de antemano.

 

Saludos

Aldo Santos

Miguel Antúnez

unread,
May 11, 2017, 9:13:15 AM5/11/17
to publice...@googlegroups.com
Estimado Aldo, trata de tener tu PK exclusivos para el sistema puede ser con tipo de campos Identity o uniqueidentifier, para  mantener tus campos únicos usa indices tipo UNIQUE. Y el borrado de todos tus registros que sean lógicos con un campo bit.
ejemplo:
CREATE TABLE [dbo].[mitabla](
[Id_tabla] [int] IDENTITY(1,1) NOT NULL,
[Campounico] [char](10) NULL,
[campos] [date] NULL,
[Estado] [bit] NULL,
 CONSTRAINT [PK_mitabla] PRIMARY KEY CLUSTERED 
(
[Id_tabla] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE UNIQUE NONCLUSTERED INDEX [identificador] ON [dbo].[mitabla]
(
[Campounico] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO



Saludos.
Miguel Antúnez C.
Lima-Perú

--
Miguel Angel Antúnez Camones
mant...@gmail.com

Carlos Miguel FARIAS

unread,
May 11, 2017, 3:19:30 PM5/11/17
to Grupo Fox
Por lo que entiendo, necesitas que una instancia en la relación (registro de tabla) mantenga por ejemplo parte de la clave sin variantes, y algo adicional que registre el cambio.

Entiendo que para el caso indicado, un código autoincremental no serviría, salvo que los cambios se lleven aparte.
Mantener los cambios en la misma tabla, si la tabla tiene mucho movimiento, puede crearte muchos registros de no proceso, que puede degradar cualquier consulta, además de que cualquier consulta tiene que "esquivar" esos datos

Varias formas de solucionarlo.
Con los cambios en la misma tabla.
Agregar a la clave primaria (que no puede ser AI) un datetime que puede ser nulo (y si el SGBD no admite nulo en la PK, un valor de fecha-hora "fuera de rango", año 3000 o año 0). Entonces el registro vigente tiene esa fecha "vacía" o fuera de rango, el registro que pasa a histórico, le colocas en el datetime mencionado, la fecha-hora en que dejo de estar vigente.
Esto es un cambio simple en la tabla, pero toda aplicación que acceda a esa tabla, debe "conocer" como esquivar los no registros "vigentes" y si cambia algo en la tabla, saber como proceder.
Esto particularmente, no me convence.

Otra forma.
Crear una bitácora donde se registre toda modificación a la tabla original. En esa tabla, colocas todos los campos de la tabla original más control de las 5W (Who, When, Where, What, hoW) o quien, cuando, donde (desde que WS), que hizo, como lo hizo.
Ese control histórico lo gestionas con triggers en el motor de base de datos (las bd nativas de fox también pueden hacerlo). No tienes que tocar la aplicación en si, solo los triggers que son parte de la bd.
Cualquier aplicación nueva que acceda a los datos de esa para altas, bajas o cambios, no tiene ni que enterarse de que ese registro de cambios se está haciendo.
Otra forma que instrumente, es que como accedo a los datos a partir de una clase de persistencia propia, dicha clase, cuando se inserta, borra o cambia cualquier tabla, guarda en una tabla común, los datos de las 5W + la clave primaria + nombre tabla + más un campo memo con los datos del registro serializados (por ejemplo JSON).
Entonces en una tabla común, tengo registro de todo lo que se toco en la BD, con la ventaja de que no tengo que meter triggers en cada tabla que se agrega al sistema y no tengo el doble de tablas de registro de modificaciones, con la contra de que si acceden sin usar el framework que diseñe, no me queda registro de cambios en las tablas.
Como ves, hay varias soluciones al problema.
Saludos: Miguel, La Pampa (RA)
Larga Vida y Prosperidad
Que la Fuerza los acompañe.

Aldo Santos

unread,
May 11, 2017, 11:16:12 PM5/11/17
to Comunidad de Visual Foxpro en Español
Hola Miguel (Peru) y Miguel (Argentina)
Gracias por sus aportes, lo que deseo hacer es algo sencillo, similar a lo que hace VFP cuando elimina un registro, sin tener que habilitar campos incrementales o guardarlas en otra tabla. Mi problema surge porque cuando coloco el campo codigo como llave principal, no puedo tener dos registros con codigo 001 mas de 1 vez, a diferencia de VFP que si puedes tener mas de una vez ese mismo codigo.

La idea es recuperar ciertos registros, en caso que un usuario elimine una información o en su defecto depurarlo con una opción.

Saludos
Aldo Santos

Carlos Miguel FARIAS

unread,
May 12, 2017, 7:08:10 AM5/12/17
to Grupo Fox
En cualquier SGBD (incluso nativas) no se puede tener dos veces el mismo valor de clave primaria (uses claves naturales o AI), en VFP, si creas un índice UNIQUE, el registro lo guarda pero el índice solo "ve" un registro, ignoro cual de los que tienen la misma clave.
En los SGBD en general, un índice UNIQUE solo admite repetir claves que son nulas.
Para lo que quieres hacer, te indiqué una opción que era sin usar autoincrementales si no que se agrega a la PK un campo (p.e. un datetime) que está con un valor extremo para el registro activo y que cuando lo das de baja, le pones la fecha correspondiente.
Ejemplo:
#DEFINE FECHA_TOPE datetime(3000, 12, 31, 23, 59, 59)
m.codigo = <un valor de código de registro>
m.fecha =  FECHA_TOPE  && esto puede estar definido como un constante FECHA_TOPE
y con esos datos grabas el registro.
Todos los del año 3000 son activos
Luego, al borrar
UPDATE tutabla SET fechaBaja = datetime() WHERE codigo = m.Codigo AND fechaBaja = FECHA_TOPE
Saludos: Miguel, La Pampa (RA)
Larga Vida y Prosperidad
Que la Fuerza los acompañe

Antonio Meza

unread,
May 12, 2017, 9:10:38 AM5/12/17
to Comunidad de Visual Foxpro en Español
Que servidor de base de datos estas usando?

Se te esta complicando pues no tienes claro para que sirve una llave primaria a mi parecer, y lo que necesitas es una llave primaria sea cual sea, es decir autoincrementable (AI) o natural, y adicional necesitas un campo para almacenar tu clave de ejemplo "001".

Es decir, el campo PK (Primary Key AI o Natural) te va a permitir relacionar registros y el campo adicional con 001, 002, etc para realizar lo que necesitas.

Seria mas fácil que pongas ejemplos de datos y que es lo que necesitas controlar para darte mas ideas.

saludos
Antonio Meza

Aldo Santos

unread,
May 16, 2017, 7:18:34 PM5/16/17
to Comunidad de Visual Foxpro en Español
Hola Antonio y Miguel,
Gracias por sus respuestas y es que viendo en VFP me estaba confundiendo la llave primaria y como se define un indice...

Al final he creado un campo llamado "scodigo_aleatorio" como PK en todas las tablas, un campo "sestado" para saber si esta borrado y adicionalmente el campo clasico "codigo" que lo uso para los indices y cualquier referencia para validacion.

Trataba de entender que un indice normal de VFP era tratado como si fuera un PK en SQL Server..

Saludos
Aldo Santos.
Reply all
Reply to author
Forward
0 new messages