Quiero almacenar una sola fila en una tabla de configuración para mi aplicación. Me gustaría hacer cumplir que esta tabla solo puede contener una fila.
¿Cuál es la forma más sencilla de aplicar la restricción de una sola fila?
sql-server
database-design
singleton
Martín
fuente
fuente
(Name, Value)
con una clave principal en el nombre? Entonces puede tener laselect Value from Table where Name = ?
certeza de que no se devolverá ninguna fila o una sola.Name
?ar
comentario s. El problema es que, si solo está almacenando pares de nombre / valor, el valor tiene que ser una cadena y no tiene forma de hacer cumplir la validación en la base de datos. Cuando usa una tabla de una sola fila con columnas separadas para cada configuración (como lo deseaba el OP), puede aplicar fácilmente la validación para cada configuración a través de restricciones de verificación.Respuestas:
Asegúrese de que una de las columnas solo pueda contener un valor y luego conviértalo en la clave principal (o aplique una restricción de unicidad).
CREATE TABLE T1( Lock char(1) not null, /* Other columns */, constraint PK_T1 PRIMARY KEY (Lock), constraint CK_T1_Locked CHECK (Lock='X') )
Tengo varias de estas tablas en varias bases de datos, principalmente para almacenar config. Es mucho más agradable saber que, si el elemento de configuración debe ser un int, solo leerá un int de la base de datos.
fuente
comp.databases.theory
un grupo de Usenet (visible a través de grupos de Google) que admito que no he leído mucho recientemente. Estaba más orientado a la teoría relacional que a SQL, pero sabía que dportas / sqlvogel también frecuentaba el mismo grupo. TTM era una referencia a The Third Manifesto , que es un buen libro que habla (de nuevo) sobre teoría relacional en lugar de SQL.Normalmente uso el enfoque de Damien, que siempre me ha funcionado muy bien, pero también agrego una cosa:
CREATE TABLE T1( Lock char(1) not null DEFAULT 'X', /* Other columns */, constraint PK_T1 PRIMARY KEY (Lock), constraint CK_T1_Locked CHECK (Lock='X') )
Añadiendo la "X" POR DEFECTO ", nunca tendrá que lidiar con la columna Bloquear, y no tendrá que recordar cuál fue el valor de bloqueo cuando cargue la tabla por primera vez.
fuente
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
Es posible que desee reconsiderar esta estrategia. En situaciones similares, a menudo me ha resultado invaluable dejar las filas de configuración antiguas por ahí para obtener información histórica.
Para hacer eso, en realidad tiene una columna adicional
creation_date_time
(fecha / hora de inserción o actualización) y un activador de inserción o inserción / actualización que la completará correctamente con la fecha / hora actual.Luego, para obtener su configuración actual, usa algo como:
select * from config_table order by creation_date_time desc fetch first row only
(dependiendo de su sabor DBMS).
De esa manera, aún puede mantener el historial para fines de recuperación (puede instituir procedimientos de limpieza si la tabla se vuelve demasiado grande, pero esto es poco probable) y aún puede trabajar con la última configuración.
fuente
SELECT TOP 1 ... ORDER BY creation_date_time DESC
Se puede implementar un LUGAR DE disparador para hacer cumplir este tipo de lógica de negocio dentro de la base de datos.
El disparador puede contener lógica para verificar si un registro ya existe en la tabla y, de ser así, ROLLBACK el Insert.
Ahora, dando un paso atrás para ver el panorama general, me pregunto si tal vez existe una forma alternativa y más adecuada para almacenar esta información, tal vez en un archivo de configuración o variable de entorno, por ejemplo.
fuente
Utilizo un campo de bits para la clave principal con el nombre IsActive. Entonces, puede haber 2 filas como máximo y el sql para obtener la fila válida es: seleccione * de Configuración donde IsActive = 1 si la tabla se llama Configuración.
fuente
Aquí hay una solución que se me ocurrió para una tabla de tipo de bloqueo que puede contener solo una fila, con una Y o N (un estado de bloqueo de la aplicación, por ejemplo).
Crea la tabla con una columna. Puse una restricción de verificación en una columna para que solo se pueda poner una Y o una N en ella. (O 1 o 0, o lo que sea)
Inserte una fila en la tabla, con el estado "normal" (por ejemplo, N significa no bloqueado)
Luego, cree un desencadenador INSERT en la tabla que solo tenga una SEÑAL (DB2) o RAISERROR (SQL Server) o RAISE_APPLICATION_ERROR (Oracle). Esto hace que el código de la aplicación pueda actualizar la tabla, pero cualquier INSERT falla.
Ejemplo de DB2:
create table PRICE_LIST_LOCK ( LOCKED_YN char(1) not null constraint PRICE_LIST_LOCK_YN_CK check (LOCKED_YN in ('Y', 'N') ) ); --- do this insert when creating the table insert into PRICE_LIST_LOCK values ('N'); --- once there is one row in the table, create this trigger CREATE TRIGGER ONLY_ONE_ROW_IN_PRICE_LIST_LOCK NO CASCADE BEFORE INSERT ON PRICE_LIST_LOCK FOR EACH ROW SIGNAL SQLSTATE '81000' -- arbitrary user-defined value SET MESSAGE_TEXT='Only one row is allowed in this table';
Funciona para mi.
fuente
Pregunta antigua, pero ¿qué tal si se usa IDENTITY (MAX, 1) de un tipo de columna pequeña?
CREATE TABLE [dbo].[Config]( [ID] [tinyint] IDENTITY(255,1) NOT NULL, [Config1] [nvarchar](max) NOT NULL, [Config2] [nvarchar](max) NOT NULL
fuente
Puede escribir un disparador en la acción de inserción en la tabla. Siempre que alguien intente insertar una nueva fila en la tabla, elimine la lógica de eliminar la última fila en el código de activación de inserción.
fuente
IF NOT EXISTS ( select * from table ) BEGIN ///Your insert statement END
fuente
Aquí también podemos hacer un valor invisible que será el mismo después de la primera entrada en la base de datos.Ejemplo: Student Table: Id: int firstname: char Aquí en el cuadro de entrada, tenemos que especificar el mismo valor para la columna id que restringirá como después de la primera entrada que no sea la escritura de bloqueo bla bla debido a la restricción de la clave principal, por lo que solo tiene una fila para siempre. ¡Espero que esto ayude!
fuente