Я хочу сохранить одну строку в таблице конфигурации для своего приложения. Я хочу сделать так, чтобы эта таблица могла содержать только одну строку.
Каков самый простой способ применить ограничение одной строки?
Я хочу сохранить одну строку в таблице конфигурации для своего приложения. Я хочу сделать так, чтобы эта таблица могла содержать только одну строку.
Каков самый простой способ применить ограничение одной строки?
Name?
arкомментарий. Проблема в том, что если вы просто храните пары имя / значение, значение вполне должно быть строкой, и у вас нет средств принудительной проверки в базе данных. Когда вы используете однострочную таблицу с отдельными столбцами для каждого параметра (как того требовал OP), вы можете легко обеспечить проверку для каждого параметра конфигурации с помощью проверочных ограничений.
Ответы:
Вы должны убедиться, что один из столбцов может содержать только одно значение, а затем сделать его первичным ключом (или применить ограничение уникальности).
CREATE TABLE T1(
Lock char(1) not null,
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
У меня есть несколько таких таблиц в разных базах данных, в основном для хранения config. Намного приятнее знать, что если элемент конфигурации должен быть int, вы когда-либо будете читать только int из БД.
comp.databases.theoryот группы usenet (видимой через группы Google), которую я, признаюсь, в последнее время мало читал. Он был больше ориентирован на теорию отношений, чем на SQL, но я знал, что dportas / sqlvogel также часто посещает ту же группу. TTM был ссылкой на «Третий манифест» , хорошую книгу, в которой (опять же) говорится о теории отношений, а не о SQL.
Обычно я использую подход Дэмиена, который всегда отлично работал у меня, но я также добавляю одну вещь:
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')
)
Добавив «DEFAULT 'X'», вам никогда не придется иметь дело со столбцом Lock, и вам не придется запоминать значение блокировки при загрузке таблицы в первый раз.
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
Вы можете переосмыслить эту стратегию. В подобных ситуациях я часто считал бесценным оставлять старые строки конфигурации без дела для исторической информации.
Для этого у вас действительно есть дополнительный столбец creation_date_time(дата / время вставки или обновления) и триггер вставки или вставки / обновления, который правильно заполнит его текущей датой / временем.
Затем, чтобы получить текущую конфигурацию, вы используете что-то вроде:
select * from config_table order by creation_date_time desc fetch first row only
(в зависимости от вашего вкуса СУБД).
Таким образом, вы по-прежнему сможете вести журнал для целей восстановления (вы можете установить процедуры очистки, если таблица станет слишком большой, но это маловероятно), и вы все равно сможете работать с последней конфигурацией.
SELECT TOP 1 ... ORDER BY creation_date_time DESC
Вы можете реализовать триггер INSTEAD OF для принудительного применения бизнес-логики этого типа в базе данных.
Триггер может содержать логику для проверки, существует ли уже запись в таблице, и если да, ОТКАТИТЬ вставку.
Теперь, сделав шаг назад, чтобы взглянуть на более широкую картину, я задаюсь вопросом, есть ли для вас альтернативный и более подходящий способ хранения этой информации, например, в файле конфигурации или переменной среды?
Я использую битовое поле для первичного ключа с именем IsActive. Таким образом, может быть не более 2 строк, а sql для получения действительной строки: выберите * из параметров, где IsActive = 1, если таблица называется Параметры.
Вот решение, которое я придумал для таблицы типа блокировки, которая может содержать только одну строку, содержащую Y или N (например, состояние блокировки приложения).
Создайте таблицу с одним столбцом. Я устанавливаю ограничение проверки для одного столбца, чтобы в него можно было поместить только Y или N. (Или 1, или 0, или что угодно)
Вставить одну строку в таблицу с "нормальным" состоянием (например, N означает не заблокировано)
Затем создайте триггер INSERT для таблицы, которая имеет только SIGNAL (DB2), RAISERROR (SQL Server) или RAISE_APPLICATION_ERROR (Oracle). Благодаря этому код приложения может обновлять таблицу, но любой INSERT не работает.
Пример 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';
Работает на меня.
Старый вопрос, но как насчет использования IDENTITY (MAX, 1) небольшого типа столбца?
CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
IF NOT EXISTS ( select * from table )
BEGIN
///Your insert statement
END
Здесь мы также можем сделать невидимое значение, которое будет таким же после первой записи в базу данных. Пример: Таблица учеников: Id: int firstname: char Здесь, в поле ввода, мы должны указать то же значение для столбца id, которое будет ограничивать как после первой записи, кроме записи lock bla bla из-за ограничения первичного ключа, таким образом, всегда остается только одна строка. Надеюсь это поможет!
(Name, Value)с первичным ключом по имени. Тогда вы можетеselect Value from Table where Name = ?с уверенностью сказать, что ни одна строка не будет возвращена.