Я хочу зберегти один рядок у таблиці конфігурації для моєї програми. Я хотів би забезпечити, щоб ця таблиця містила лише один рядок.
Який найпростіший спосіб застосувати обмеження для одного рядка?
Я хочу зберегти один рядок у таблиці конфігурації для моєї програми. Я хотів би забезпечити, щоб ця таблиця містила лише один рядок.
Який найпростіший спосіб застосувати обмеження для одного рядка?
Name
?
ar
коментар s. Проблема полягає в тому, що якщо ви просто зберігаєте пари ім’я / значення, значення досить добре має бути строковим, і у вас немає засобів для забезпечення перевірки в базі даних. Коли ви використовуєте однорядкову таблицю з окремими стовпцями для кожного параметра (як вимагав OP), ви можете легко примусити перевірку для кожного параметра конфігурації за допомогою обмежень перевірки.
Відповіді:
Ви переконайтесь, що один із стовпців може містити лише одне значення, а потім переконайтеся, що первинний ключ (або застосуйте обмеження унікальності).
CREATE TABLE T1(
Lock char(1) not null,
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
У мене є ряд цих таблиць у різних базах даних, в основному для зберігання конфігурації. Набагато приємніше знати, що якщо елемент конфігурації повинен бути 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')
)
Додаючи "ЗАВДАННЯ 'X'", вам ніколи не доведеться мати справу зі стовпцем Блокування та не доведеться згадувати, яке значення блокування було при першому завантаженні таблиці.
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, який має лише СИГНАЛ (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';
Працює для мене.
Старе питання, а як щодо використання ІДЕНТИЧНОСТІ (МАКС., 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, яке обмежить як після першого входу, крім написання бла бла бла через обмеження первинного ключа, таким чином, назавжди має лише один рядок. Сподіваюся, це допомагає!
(Name, Value)
з первинним ключем на Name. Тоді ви можетеselect Value from Table where Name = ?
з упевненістю сказати, що не буде повернуто жодного рядка або один рядок.