Can any body give the suggestions.Why I am getting this error.
System.Data.SqlClient.SqlException: The INSERT statement conflicted with the CHECK constraint «CK_GL10000_TRXDATE__56701F76″. The conflict occurred in database «TWO», table «dbo.GL10000», column ‘TRXDATE’.
This is my stored procedure :
SqlCommand myCommand1 = new SqlCommand("taGLTransactionHeaderInsert", strcon);
myCommand1.CommandType = CommandType.StoredProcedure;
myCommand1.CommandText = "taGLTransactionHeaderInsert";
myCommand1.Parameters.Add("@I_vBACHNUMB", SqlDbType.Char).Value = GLHdr.BACHNUMB;
myCommand1.Parameters.Add("@I_vREFRENCE", SqlDbType.Char).Value = "ExcelImport";
myCommand1.Parameters.Add("@I_vTRXDATE", SqlDbType.DateTime).Value = GLHdr.TRXDATE;
Table definition:
CREATE TABLE [dbo].[GL10000](
[PSTGSTUS] [smallint] NOT NULL,
[LASTUSER] [char](15) NOT NULL,
[LSTDTEDT] [datetime] NOT NULL,
[USWHPSTD] [char](15) NOT NULL,
[TRXTYPE] [smallint] NOT NULL
/* More columns? not included in script that OP added */
)
GO
ALTER TABLE [dbo].[GL10000] WITH CHECK ADD CHECK
((datepart(hour,[RVRSNGDT])=(0) AND datepart(minute,[RVRSNGDT])=(0)
AND datepart(second,[RVRSNGDT])=(0) AND datepart(millisecond,[RVRSNGDT])=(0)))
GO
ALTER TABLE [dbo].[GL10000] WITH CHECK ADD CHECK
((datepart(hour,[Tax_Date])=(0) AND datepart(minute,[Tax_Date])=(0)
AND datepart(second,[Tax_Date])=(0) AND datepart(millisecond,[Tax_Date])=(0)))
GO
ALTER TABLE [dbo].[GL10000] WITH CHECK ADD CHECK
((datepart(day,[TIME1])=(1) AND datepart(month,[TIME1])=(1)
AND datepart(year,[TIME1])=(1900)))
GO
ALTER TABLE [dbo].[GL10000] WITH CHECK ADD CHECK
((datepart(hour,[TRXDATE])=(0) AND datepart(minute,[TRXDATE])=(0)
AND datepart(second,[TRXDATE])=(0) AND datepart(millisecond,[TRXDATE])=(0)))
GO
ALTER TABLE [dbo].[GL10000] ADD CONSTRAINT
[DF__GL10000__DEX_ROW__540C7B00] DEFAULT (getutcdate()) FOR [DEX_ROW_TS]
GO
The solution for above subject line exists in many links and have come across all links and find no solution for my issue.
here is my query :
INSERT INTO PatientPatternElements (PatientPatternsID, ASEventID, LocationID, EffectiveDate, EffectiveDateEnd, WorkloadStartDate, WorkloadEndDate)
SELECT DISTINCT PatientPatterns.ID,
@hl7event_id,
@default_locationid,
@hl7event_effective_date,
@hl7event_effective_date,
@hl7event_effective_date,
@hl7event_effective_date
FROM PatientPatternElements
INNER JOIN PatientPatterns
ON PatientPatternElements.PatientPatternsID = PatientPatterns.ID
WHERE PatientPatterns.PatientEncounterID = @patient_encounter_id
AND PatientPatterns.Visit = @patient_encounter_visit
---------------------
-- Error Checking
----------------------
SET @SysError = @@error
IF @SysError != 0
BEGIN
SET @iError = 23063
SET @strErrorMsg = 'Error Applying Manual Discharge Event, Error: ' + cast(@SysError AS varchar(256)) + ' encounter_id=' + cast(@patient_encounter_id as varchar(64))
GOTO ERROR
END
It is just a part of my code of my stored procedure.
WORKFLOW
It is happening in one of the version in client testing environment and client has one more version and the flow works without any issues.
when we are trying to run a record manually it is throwing an error in one of our log table and throws below message:
THREAD 4: ApplyPatientPatternEvents: Recovering from SQL exception: The INSERT statement conflicted with the CHECK constraint "CK_PatientPatternElements_Location".
The conflict occurred in database "db_name", table "dbo.PatPatternElements".
and this
Rolling back Transaction. spHL7ApplyPatientPatternEvents: Error Applying Manual Discharge Event, Error: 547 encounter_id=20
as I said earlier it is happening in only one version, stored procedure is identical in both the versions, making hard to find out the issue.
there is nothing logged in Eventviewer and tracing sql profiler also not helping much since the SP spHL7ApplyPatientPatternEvents
never show up in profiler.
Anyone can give an idea what exactly has happened ?
This is the query of constraint.
ALTER TABLE [dbo].[PatientPatternElements] WITH CHECK ADD CONSTRAINT [CK_PatientPatternElements_Location] CHECK (([LocationID] IS NULL AND [LevelOfCareGroupID] IS NOT NULL OR [LocationID] IS NOT NULL AND [LevelOfCareGroupID] IS NULL))
GO
ALTER TABLE [dbo].[PatientPatternElements] CHECK CONSTRAINT [CK_PatientPatternElements_Location]
GO
Время на прочтение
2 мин
Количество просмотров 26K
Кто-то задал такой вопрос:
Мне нужно создать таблицу group со столбцом code. Можно ли добавить ограничение на столбец, которое допускало бы только буквенные символы (D, M, O, P или T) с последующими двумя цифровыми символами?
Ему ответили:
Вы не можете этого сделать обычным способом — MS SQL Server поддерживает проверку ограничений, но лишь в виде мин/макс значения INT, длины строки и т.п. То, что вам нужно, — проверка на основе регулярного выражения, которую SQL Server не поддерживает. Теоретически можно сделать .NET вставку, развернуть на SQL Server и заставить его использовать такую проверку — нетривиальная задача.
Попробуем разобраться
Не смотря на то, что SQL server не поддерживает регулярные выражения в полной мере, но поставленную выше задачу можно без проблем решить и на T-SQL. Вот так будет выглядеть это регулярное выражение
[DMOPT][0-9][0-9]
Оно допускает только буквенные символы (D, M, O, P или T) с последующими двумя цифровыми символами. Ладно, хватит разговоров, давайте перейдем к коду
Создадим таблицу
CREATE TABLE blatest(code char(3))
Добавим проверку ограничения
ALTER TABLE blatest ADD CONSTRAINT ck_bla
CHECK (code like '[DMOPT][0-9][0-9]' )
GO
Теперь несколько инструкций для вставки данных
INSERT blatest VALUES('a12') --недопустимое значение
INSERT blatest VALUES('M12') --допустимое значение
INSERT blatest VALUES('D12') --допустимое значение
INSERT blatest VALUES('DA1') --недопустимое значение
Как видите, мы дважды получили сообщение об ошибке
Сообщение 547, уровень 16, состояние 0, строка 1
Конфликт инструкции INSERT с ограничением CHECK "ck_bla". Конфликт произошел в базе данных "Test", таблица "dbo.blatest", столбец 'code'.
Выполнение данной инструкции было прервано.
Если вы хотите выполнить вставку D12, а не d12, т.е. нужна чувствительность к регистру, тогда нужно создать такое ограничение
(code like '[DMOPT][0-9][0-9]' COLLATE SQL_Latin1_General_CP1_CS_AS )
Все, что потребовалось изменить — добавить параметр сортировки SQL_Latin1_General_CP1_CS_AS.
Чтобы узнать, что дает этот параметр, выполните следующий запрос
SELECT * FROM ::fn_helpcollations()
WHERE name = 'SQL_Latin1_General_CP1_CS_AS'
Вот, что вернул запрос в описании
Latin1-General, case-sensitive, accent-sensitive, kanatype-
insensitive, width-insensitive for Unicode Data, SQL Server Sort Order 51 on Code Page 1252 for non-Unicode Data
Давайте создадим новое ограничение, но прежде нам нужно удалить старое
ALTER TABLE blatest DROP CONSTRAINt ck_bla
GO
Теперь создаем новое и проверяем
ALTER TABLE blatest ADD CONSTRAINT ck_bla
CHECK (code LIKE '[DMOPT][0-9][0-9]' COLLATE SQL_Latin1_General_CP1_CS_AS )
GO
INSERT blatest VALUES('D12') --допустимое значение
INSERT blatest VALUES('d12') --недопустимое значение
Вставка значения D12 будет успешной, а d12 — нет.
Как видите, использовать регулярные выражения в ограничениях можно и никакой триггер в данном случае не нужен.
Оператор INSERT конфликтует с ограничением CHECK «ck_str_member_no
«. Конфликт произошел в базе данных «C: ДОКУМЕНТЫ И НАСТРОЙКИ KARTHIKEYAN DESKTOP KOK DB INFT3009_ASS1_C3104855.MDF», таблица «dbo.Members», столбец ‘str_member_no
‘. Заявление было прекращено.
Я использую файл .MDF в своей Visual Studio 2008 Express. Как мне это решить?
Моя процедура вставки:
ALTER PROCEDURE [dbo].[AddNewAGCMember]
-- Add the parameters for the stored procedure here
@str_member_no varchar(6) = '',
@str_member_name varchar(50) = '',
@str_member_password varchar(10) = '',
@str_addr_apartment_no varchar(10) = NULL,
@str_addr_building_name varchar(50) = NULL,
@str_addr_street_name varchar(50) = NULL,
@int_postal_code int = NULL,
@str_country_name varchar(50) = NULL,
@int_contact_no int = NULL,
@str_email_addr varchar(100) = '',
@date_registration date = ''
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO Members
(str_member_no,
str_member_name,
str_member_password,
str_addr_apartment_no,
str_addr_building_name,
str_addr_street_name,
int_postal_code,
str_country_name,
int_contact_no,
str_email_addr,
date_registration)
VALUES
(@str_member_no,
@str_member_name,
@str_member_password,
@str_addr_apartment_no,
@str_addr_building_name,
@str_addr_street_name,
@int_postal_code,
@str_country_name,
@int_contact_no,
@str_email_addr,
@date_registration);
END
Структура таблицы:
str_member_no
, varchar (6), не отмеченstr_member_name
, varchar (50), не отмеченоstr_member_password
, varchar (10), не отмеченоstr_addr_apartment_no
, varchar (10), провереноstr_addr_building_name
, varchar (50), Провереноstr_addr_street_name
, varchar (50), провереноint_postal_code
, int, Провереноstr_country_name
, varchar (50), провереноint_contact_no
, int, Провереноstr_email_addr
, varchar (100), не отмечено-
date_registration
, дата, не отмеченоUnchecked
Задача любого администратора и программиста, совместно обеспечить целостность и корректность данных. Например, если пользователь не укажет в одной из строк в списке жителей дома фамилию, то корректность данных портиться. Человека очень сложно найти, если не известна его фамилия.
А что если в нашем списке добавить поле для хранения пола. Что можно записать в такое поле? Конечно же, достаточно одной буквы «М» или «Ж», другого пола пока не придумали :). А что если пользователь случайно введет букву «Ь»? Это не смешно, а вполне реальная ситуация. Посмотрите на клавиатуру и увидите, что на ней две буквы «М», просто одна английская, а другая русская. На одной клавише с английской буквой «М» находиться «Ь». Начинающие пользователи нередко путаются и если не проверят результат своего ввода, то корректность данных нарушается.
Нередко бывают ситуации, когда вместо русской буквы М пользователь вводить английскую. В этом случае в базе получается три пола: М русская, М английская и Ж. Конечно, программно эта ситуация решается достаточно просто, достаточно только при определении мужчин выбирать из базы все записи с буквой М в любой раскладке, но качество такой базы будет далеко от идеала.
Все эти проблемы известны уже давно и для их решения придумали ограничения – универсальное средство, с помощью которого можно задать правила, которым должны удовлетворять данные, для возможности записи в поле. Если записываемое значение не удовлетворяет ограничениям, назначенным полю, то запись завершается ошибкой. Таким образом, сервер сам будет контролировать целостность данных, вводимых пользователем.
Самое простейшее ограничение – это разрешение или запрещение введения нулевых значений (NULL). Тут нужно отметить, что NULL и пустая строка это совершенно разные вещи. Об этом мы еще поговорим во второй главе. Итак, для таблицы, в которой хранятся ФИО, пол и дата рождения не нулевыми должны быть фамилия, имя и пол. Эти параметры есть у каждого жителя нашей страны, поэтому в базе данных обязательно должно быть что-то указано, иначе будет сгенерирована ошибка и сервер не позволит записать такую строку.
А вот с отчеством и датой рождения бывают проблемы, особенно у тех, кто родился во время второй мировой войны. В те времена сложно было определить дату рождения сирот, а в детских домах после войны детям давали только имя и отчество, поэтому отсутствие этих параметров не будет считаться ошибкой.
Следующий пример, показывает, как создаются поля, в которых запрещаются пустые значения:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, dDate datetime DEFAULT (getdate()) NULL, vcName varchar(50) NOT NULL )
В данном случае указано, что поле id и vcName не могут содержать нулевые значения. Пользователь обязательно должен указать хоть что-нибудь, иначе изменения не будут приняты, и сервер сгенерирует ошибку. А вот поле dDate может содержать нулевое значение NULL.
Что не корректно в этом примере? Хотя нет, некорректного ничего нет, но на первый взгляд есть одна глупость. Для поля dDate мы разрешили нулевое значение, но это бессмысленно. Дело в том, что у этого поля есть значение по умолчанию, а значит, если в поле будет попытка записать нулевое значение, оно будет автоматически заменено на значение по умолчанию. Получается, что указывать NULL бессмысленно, если для поля установлено значение по умолчанию и нулевого значения просто не будет.
Но теперь вспомним, когда генерируется значение по умолчанию – только при вставке строки, а не при обновлении. Вы уловили ход мысли? Если полю назначено значение по умолчанию и при этом запрещено нулевое значение, то ноль нельзя будет установить даже у существующей строки. Именно поэтому я сказал, что глупость есть только на первый взгляд. Никогда не забывайте, когда устанавливается значение по умолчанию.
Ограничения NULL и NOT NULL являются не жесткими и некоторые специалисты даже не относят их к ограничениям, хотя, по своей сути они такими являются. Более жесткие ограничения задаются оператором CHECK. Рассмотрим этот оператор на примере. Допустим, что нам нужно создать список хозяев квартир. Для этого нам понадобиться ключевое поле («id»), имя хозяина («vcName») и номер квартиры («iApartment»). Для квартиры вполне логичным будет сделать ограничение ввода от 1 до 1000. Квартир с отрицательными номерами и нулевыми значениями не бывает (по крайней мере, в моем городе), да и более 1000 у нас не бывает, я даже не видел квартиры, с номером более 400. Поэтому логично будет запретить ввод явно некорректных данных с помощью ограничения. Итак, посмотрим на следующий запрос создания таблицы:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, vcName varchar(50) NOT NULL, iApartment int CHECK (iApartment>0 and iApartment<1000) )
После указания имени и типа поля «iApartment» указано ключевое слово CHECK, после которого в круглых скобках необходимо указать ограничения для данного поля. В нашем примере в качестве ограничения выступает:
iApartment>0 and iApartment<1000
Это значит, что значение в поле iApartment должно быть более 0 и в то же время меньше 1000. Объединение происходит с помощью ключевого слова and, то есть «и». Это значит, что оба условия должны быть выполнены. Бывают случаи, когда необходимо, чтобы хотя бы одно из условий было выполнено, тогда их объединяют оператором or. Например, нужно чтобы в поле заносилось значение или меньше нуля, или больше 1000. Значения в промежутке 1 – 1000 указывать нельзя. В этом случае, сравнение выглядело бы:
iApartment<0 or iApartment>1000
Попробуйте вставить в таблицу квартир данные. Для этого давайте выполним три запроса. Первый будет вставлять корректные данные:
INSERT INTO TestTable(vcName, iApartment) VALUES('Корректная запись', 10)
Не будем вдаваться в подробности работы запроса, это нам предстоит узнать во 2-й главе. Операция пройдет успешно и никаких ошибок не появиться. Следующий запрос будет пытаться вставить запись с номером квартиры 10000, что не соответствует ограничению:
INSERT INTO TestTable(vcName, iApartment) VALUES('Ошибочная запись', 10000)
В ответ на это, перед нами должно появиться окно с сообщением об ошибке:
INSERT statement conflicted with COLUMN CHECK constraint ‘CK__TestTable__iApar__22AA2996’. The conflict occurred in database ‘TestDatabase’, table ‘TestTable’, column ‘iApartment’.
The statement has been terminated.
Оператор INSERT конфликтует с COLUMN CHECK ограничением ‘CK__TestTable__iApar__22AA2996’. Конфликт обнаружен в базе данных ‘TestDatabase’, таблица ‘TestTable’, колонка ‘iApartment’.
Выполнение было прервано.
Эта ошибка может быть отображена и в окне результата выполнения запроса, а не в отдельном окне диалога. Смысл сообщения в том, что произошел конфликт с ограничением данных.
Если с помощью Enterprise Manager открыть свойства таблицы TestDatabase, то в появившемся окне на закладке Check Constraints в выпадающем списке Selected constraint выбрать ограничение, которое мы увидели в сообщении (CK__TestTable__iApar__22AA2996), а в окне Constraint expression появится описание ограничения.
Напоследок, выполним запрос, который покажет содержимое таблицы:
SELECT * FROM TestTable
Вы должны увидеть только одну строку, которую мы создали первой с корректными значениями. Некорректная строка будет отсутствовать в таблице.
Самое неприятное в этом примере – это имя ограничения, которое было назначено автоматически — CK__TestTable__iApar__22AA2996. С такими именами очень неудобно работать, намного приятнее видеть читаемые имена и со смыслом. Чтобы задать имя ограничению, необходимо использовать конструкцию:
CONSTRAINT имя CHECK (ограничения)
Внимание
Имена ограничений внутри базы данных должны быть уникальными. Это значит, что вы не можете создать два ограничения с одним и тем же именем не только для одной и той же таблицы, но и для разных таблиц одной базы данных.
Такие ограничения можно описывать внутри описания поля (как параметры), а можно вынести все в один блок, после описания полей. В этом случае, ограничение должно выглядеть следующим образом:
CONSTRAINT Имя ограничения CHECK (Ограничение)
Такое ограничение желательно описывать после всех полей и через запятую, как и поля таблицы. Преимущество такого метода в том, что мы сами задаем имя ограничения, и с ним будет удобнее работать в дальнейшем.
Давайте удалим старую таблицу, а создадим новую с еще одним полем – dDate типа datetime. Для этого поля поставим ограничение, которое позволит вводить только даты, которые меньше текущей:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, vcName varchar(50) NOT NULL, iApartment int, dDate datetime, CONSTRAINT check_iApartment CHECK (iApartment>0 and iApartment<1000), CONSTRAINT check_dDate CHECK (dDate<getdate()) )
Как видите, в этом примере ограничения описываются через запятую, так же, как и поля. После ключевого слова CONSTRAINT указывается имя ограничения. Из своей практики хочу порекомендовать называть их в виде check_имя, где имя – имя поля, которое проверяется ограничением. После этого указывается само ограничение точно также как и в предыдущем примере.
Обратите внимание, что для ограничения ввода в поле «dDate» мы использовали функцию (getdate). Как и при описании значений по умолчанию, в ограничениях также могут использоваться функции.
При создании ограничения, можно использовать многие операторы сравнения языка SQL. Например, в SQL есть очень удобный оператор IN. С его помощью можно задать возможные значения для поля, которые оно может принимать. Например, вам нужно в таблице ограничить ввода данных в поле содержащую такую информацию как пол человека. В этом случае, можно разрешить ввод букв «М» и «Ж» следующим образом:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, vcName varchar(50) NOT NULL, cPol char(1), CONSTRAINT check_cPol CHECK (cPol IN ('М', 'Ж')) )
В данном случае, ограничение выглядит следующим образом: cPol IN (‘М’, ‘Ж’). Оператор IN означает, что поле может принимать любые значения, перечисленные в круглых скобках. В нашем случае указано две строки ‘М’ и ‘Ж’. Другие буквы вносить в поле нельзя. Конечно же, то же самое можно было бы написать и следующим образом:
(cPol = 'М' or cPol = 'Ж')
Но это не очень удобно, особенно, если очень много возможных вариантов. Ограничение окажется не очень удобным для чтения. Оператор IN в этом случае намного красивее и читабельнее.
Очень мощных возможностей можно добиться, используя в ограничении оператора LIKE. Например, вы хотите, чтобы поле для хранения телефонного номера содержало номер в формате (ХХХ) ХХХ-ХХ-ХХ, где Х – это любая цифра. Для реализации примера такого ограничения создадим новую таблицу с полем «vcPhonenumber»:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, vcPhonenumber varchar(50) NOT NULL CONSTRAINT check_vcPhonenumber CHECK (vcPhonenumber LIKE '([0-9][0-9][0-9]) [0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]') )
В данном случае, ограничение с именем check_vcPhonenumber при проверки использует оператор LIKE. С этим оператором мы познакомимся ближе в следующей главе, когда будем изучать работу с оператором SELECT, но я решил вставить этот пример, чтобы вы заранее знали о его мощи. Если классический знак равенства производит жесткое сравнение, то LIKE позволяет сравнивать строки с определенным шаблоном. В данном случае шаблоном является:
([0-9][0-9][0-9]) [0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
В квадратных скобках мы указываем возможный диапазон символа. В данном случае, диапазон от 0 до 9. Если заменить все [0-9] на Х, то мы получим искомый шаблон (ХХХ) ХХХ-ХХ-ХХ. Следующий пример запроса добавляет в таблицу номер телефона (085) 880-08-00:
INSERT INTO TestTable(vcPhonenumber) VALUES('(085) 880-08-00')
Операция пройдет успешно. Но если убрать пробел, или любой из символов ( или -, или заменить какую-либо цифру буквой, то операция завершиться неудачей:
INSERT INTO TestTable(vcPhonenumber) VALUES('(095)8800800')
В ответ на это мы увидим сообщение:
INSERT statement conflicted with COLUMN CHECK constraint ‘check_vcPhonenumber’. The conflict occurred in database ‘TestDatabase’, table ‘TestTable’, column ‘vcPhonenumber’.
The statement has been terminated.
Смысл сообщения в следующем: «Оператор INSERT конфликтует с ограничением COLUMN CHECK с именем check_vcPhonenumber. Конфликт появился в базе данных TestDatabase, таблице TestTable, колонке vcPhoneNumber. Выполнение оператора прервано».
Следующий пример задает шаблон для ввода даты:
CREATE TABLE TestTable ( id int DEFAULT 1 NOT NULL, vcDate varchar(50) NOT NULL CONSTRAINT check_vcDate CHECK (vcDate LIKE '[0-3][0-9].[0-1][0-9].[0-9][0-9][0-9][0-9]') )
Такой шаблон бывает удобным, если дату нужно хранить в текстовом виде. Да, есть специализированный тип datetime, но все же, бывают разные задачи и может пригодиться текстовый хранение. Шаблон, позволяет ограничить действия пользователя, дабы уменьшить вероятность ошибки, но не решает задачу полностью. Давайте посмотрим на него по частям.
Первая часть (до точки) определяет число месяца. Первая цифра числа может принимать значения от 0 до 3, а вторая цифра от 0 до 9. Это значит, что пользователь может ввести числа от 01 до 39. Числа от 32 до 39 заранее являются не корректными. При указании месяца пользователь также может указать неверное значение, потому что это значение мы ограничили значениями от 01 до 19.
Бывает необходимость, чтобы определенное поле или сочетание полей были в базе данных уникальными. Это можно проверять с помощью запросов самостоятельно, а можно доверить проверку серверу. Для создания ограничения уникальности используется ограничение UNIQUE, которое выглядит следующим образом:
CONSTRAINT Имя ограничения UNIQUE (Поле или список полей)
Следующий пример создает ограничение уникальности для ключевого поля idName, ведь не даром оно ключевое, и должно быть уникальным:
CREATE TABLE Names ( idName int, vcName varchar(50), vcLastName varchar(50), vcSurName varchar(50), dBirthDay datetime, CONSTRAINT cn_unique UNIQUE (idName) )
Недавно мне пришлось разрабатывать базу данных, в которой формировалась отчетность из списка клиентов организации. Когда я начал работать с базой данных, то оказалось, что в базе есть дубликаты клиентов. В старой базе данных не было проверок на двойственность записей, только не эффективные проверки в пользовательской программе.
Самая простая проверка на двойников проходила выявлением записей, где полностью совпадали ФИО и дата рождение клиента. Вероятность совпадения всех этих параметров внутри одного города стремиться к нулю. Таким образом, необходимо было всего лишь добавить ограничение, при котором сочетание из этих полей было уникальным. Это можно сделать следующим образом:
CREATE TABLE Names ( idName int , vcName varchar(50), vcLastName varchar(50), vcSurName varchar(50), dBirthDay datetime, CONSTRAINT cn_unique UNIQUE (vcName, vcLastName, vcSurName, dBirthDay) )
В данном примере создается таблица из полей: идентификатора, имени, фамилии, отчества и даты рождения. После этого, создается ограничение, при этом оно имеет тип не CHECK, а UNIQUE. В скобках указываются поля, которые должны быть уникальными. В данном примере, я перечислил поля фамилия, имя, отчество и дата рождения. Таким образом, база данных не позволит создать дубликат записи.