Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Проверка допустимости значения поля с помощью сравнения с полем другой таблицы  (Прочитано 10943 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Maximys
Новенький

ru
Offline Offline

« : 27-04-2012 23:52 » 

Занимаюсь самостоятельным изучением MS SQL Server, в следствии чего возник небольшой вопрос.
Создаю базу с помощью следующего SQL-запроса:
Код:
CREATE TABLE [Entity1]
(
 [Уникальный_таблица1] Uniqueidentifier NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Varchar(100) NULL,
 [Attribute4] Tinyint NOT NULL,
 [ID] Char(10) NOT NULL
)
go

-- Add keys for table Entity1

ALTER TABLE [Entity1] ADD CONSTRAINT [Key1] PRIMARY KEY ([Уникальный_таблица1],[ID])
go

-- Create triggers for table Entity1

CREATE TRIGGER [Trigger1]
  ON [Entity1]
  AFTER INSERT, UPDATE
  AS
declare
        @attr3 tinyint,
        @attr4 tinyint
        
            select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=Entity1.[ID]
            select @attr4=[Attribute4] from [Entity1]
IF @attr4>=@attr3
    RaisError('Ошибка', 16,1)
go

-- Table Entity2

CREATE TABLE [Entity2]
(
 [ID] Char(10) NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Tinyint NULL
)
go

-- Add keys for table Entity2

ALTER TABLE [Entity2] ADD CONSTRAINT [Key2] PRIMARY KEY ([ID])
go

-- Create relationships section -------------------------------------------------

ALTER TABLE [Entity1] ADD CONSTRAINT [Relationship1] FOREIGN KEY ([ID]) REFERENCES [Entity2] ([ID])
go
Триггер Trigger1 нужен для того, чтобы гарантировать выполнение условия: [Entity1].[Attribute4>=[Entity2].[Attribute3].
Запрос отлично выполняется. Теперь пытаюсь заполнить БД вручную. Entity2 отлично заполняется, например строка с данными: [ID]='1', [Attribute2]='2', [Attribute3]='3' превосходно вставилась. Теперь пытаюсь заполнить Entity1: [Уникальный_таблица1]='41d07060-c65a-470a-a9e0-0530ae9be53e', [Attribute2]='4', [Attribute3]='5', [Attribute4]='6', [ID]='1', но в ответ получаю ошибку:

Подскажите, почему возникает такая проблема, что не так в моем запросе?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 28-04-2012 03:28 » 

Код: (SQL)
SELECT @attr3=[Attribute3] FROM [Entity2] WHERE Entity2.[ID]=Entity1.[ID]
А что такое Entity1 в данном запросе?

Прежде чем ставить запросы в тригеры, протестируй вначале на правильность.
« Последнее редактирование: 28-04-2012 03:41 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #2 : 28-04-2012 04:32 » 

не сильно работал с тригерами, но
во-первых: тут ошибка

Код:
select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=Entity1.[ID]
select @attr4=[Attribute4] from [Entity1]

в тригере идёт работа с виртуальными таблицами inserted и deleted
т.е надо писать примерно так

Код:
select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=inserted .[ID]
select @attr4=[Attribute4] from [inserted]

во вторых:
 обновлятся и добавлятся могут более одной записи за один батч и этот запрос при таком батче
либо неправильно отработает, либо даст ошибку
Код:
select @attr4=[Attribute4] from [inserted]

в третьих: я бы сделал лучше констрейнт вместо тригера
для этого создал бы скалярную инлайн функцию
Код:
create function dbo.ZZZ(@ID Char(10))
RETURNS Tinyint
As (select [Attribute3] from [Entity2] where Entity2.[ID]=@ID )
и создал бы на таблице Entity1 констрейнт
Код:
ALTER TABLE Entity1 WITH NOCHECK 
ADD CONSTRAINT Attribute4_check CHECK (Attribute4 > dbo.ZZZ(ID))



PS: привыкайте сразу у всех объектов прописывать схему
Записан

I Have Nine Lives You Have One Only
THINK!
Maximys
Новенький

ru
Offline Offline

« Ответ #3 : 28-04-2012 07:02 » 

в третьих: я бы сделал лучше констрейнт вместо тригера
для этого создал бы скалярную инлайн функцию
Код:
create function dbo.ZZZ(@ID Char(10))
RETURNS Tinyint
As (select [Attribute3] from [Entity2] where Entity2.[ID]=@ID )
и создал бы на таблице Entity1 констрейнт
Код:
ALTER TABLE Entity1 WITH NOCHECK 
ADD CONSTRAINT Attribute4_check CHECK (Attribute4 > dbo.ZZZ(ID))
Пытаюсь последовать Вашему совету: заменить триггер на CONSTRAINT. Изменил SQL-запрос для создания БД на следующий(хочется "на пальцах" все верно построить, а не исправлять полученный баг):
Код:
CREATE TABLE [Entity1]
(
 [Уникальный_таблица1] Uniqueidentifier NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Varchar(100) NULL,
 [Attribute4] Tinyint NOT NULL,
 [ID] Char(10) NOT NULL,
  CONSTRAINT [Attribute4_check] CHECK (Attribute4 > ZZZ(ID))
)
go

-- Add keys for table Entity1

ALTER TABLE [Entity1] ADD CONSTRAINT [Key1] PRIMARY KEY ([Уникальный_таблица1],[ID])
go

-- Table Entity2

CREATE TABLE [Entity2]
(
 [ID] Char(10) NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Tinyint NULL
)
go

-- Add keys for table Entity2

ALTER TABLE [Entity2] ADD CONSTRAINT [Key2] PRIMARY KEY ([ID])
go

-- Create functions section -------------------------------------------------

CREATE FUNCTION [ZZZ] (@ID Char(10))
RETURNS Tinyint
AS
BEGIN
Declare @returnedValue Tinyint
    SELECT @returnedValue= [Attribute3] FROM [Entity2] WHERE Entity2.[ID]=@ID

RETURN @returnedValue
END
go

-- Create relationships section -------------------------------------------------

ALTER TABLE [Entity1] ADD CONSTRAINT [Relationship1] FOREIGN KEY ([ID]) REFERENCES [Entity2] ([ID])
go
Но при попытке выполнить данный код получаю ошибки:
Цитата
"Сообщение 195, уровень 15, состояние 10 ZZZ не является известным имя встроенной функции.
Сообщение 4902, уровень 16, состояние 1, строка 4 Не удалось найти объект "Entity1", так как он не существует, или отсутствуют разрешения.
Сообщение 4902, уровень 16, состояние 1, строка 4 Не удалось найти объект "Entity1", так как он не существует, или отсутствуют разрешения."
Последние две ошибки понятно с чем связаны - т.к. ZZZ неизвестна, то Entity1 не создалась. Причина первой ошибки тоже понятна - ZZZ определяется ниже, но куда тогда надо "всунуть" в запросе эту функцию, чтобы он нормально исполнился(если впихнуть её перед определением таблиц, то получим аналогичную ошибку, но по отношению к Entity2) или функцию ZZZ и ограничения на Attribute4 нужно вставлять с помощью отдельного запроса после вставки всех таблиц?
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 28-04-2012 07:43 » 

А с этим
select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=Entity1.[ID]

разобрались?

А проверь-ка такую последовательность на бумаге

            select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=Entity1.[ID]
            select @attr4=[Attribute4] from [Entity1]
IF @attr4>=@attr3

Что будет? если вернется несколько записей?
или null
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Maximys
Новенький

ru
Offline Offline

« Ответ #5 : 28-04-2012 07:45 » new

А с этим
select @attr3=[Attribute3] from [Entity2] where Entity2.[ID]=Entity1.[ID]

разобрались?
Вполне, а что? Так все таки как можно решить вышеописанную проблему?
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 28-04-2012 08:14 » 


Вполне, а что? Так все таки как можно решить вышеописанную проблему?
Что вполне?
А какая проблема?
В том что неверно написан запрос

А на второй вопрос Вы не ответили!!!
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #7 : 28-04-2012 08:25 » 

конечно будет ошибка т.к в этот момент ф-цииеще нет

Код:
CREATE TABLE [Entity1]
(
 [Уникальный_таблица1] Uniqueidentifier NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Varchar(100) NULL,
 [Attribute4] Tinyint NOT NULL,
 [ID] Char(10) NOT NULL,
  CONSTRAINT [Attribute4_check] CHECK (Attribute4 > ZZZ(ID))
)
go
измените скрипт

Код:
CREATE TABLE [Entity1]
(
 [Уникальный_таблица1] Uniqueidentifier NOT NULL,
 [Attribute2] Varchar(100) NULL,
 [Attribute3] Varchar(100) NULL,
 [Attribute4] Tinyint NOT NULL,
 [ID] Char(10) NOT NULL
)
go
-- тута создание всего остального и ф-ции
go
ALTER TABLE Entity1 WITH NOCHECK
ADD CONSTRAINT Attribute4_check CHECK (Attribute4 > dbo.ZZZ(ID))



Цитата: Sla
select @attr4=[Attribute4] from [Entity1]
Что будет? если вернется несколько записей?
или null
позволю себе ответить
если в таблице будет несколько записей, то значение @attr4 будет неопределеенно (любое из всех значений в таблице)
Записан

I Have Nine Lives You Have One Only
THINK!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines