2009-05-20 2 views
0

Good DayВ чем разница между двумя операторами sql?

Все, что мы пытаемся сделать, находится внутри триггера, убедитесь, что пользователь не вставляет две платы, которые имеют «один» в имени. Эти сборы должны обрабатываться индивидуально.

По какой-то причине он выглядит верхней частью sql quit, работающей две недели назад. Чтобы обойти это, я переписал его вторым способом и получил правильные результаты. Я смущен, почему первая часть показалась, чтобы работать последние несколько лет, а теперь нет?

SELECT @AloneRecordCount = count(*) 

FROM inserted i 
     INNER JOIN deleted d on i.id = d.id 

WHERE i.StatusID = 32 
     AND d.StatusID <> 32 
     AND i.id IN 
     (SELECT settlementid FROM vwFundingDisbursement fd 
     WHERE fd.DisbTypeName LIKE '%Alone' 
     AND fd.PaymentMethodID = 0) 


SELECT @AloneRecordCount = count(i.id) 

FROM inserted i INNER JOIN 
     deleted d on i.id = d.id 
     JOIN vwFundingDisbursement fd on i.id = fd.settlementid 

WHERE i.StatusID = 32 
     AND d.StatusID <> 32 
     AND fd.DisbTypeName like '%Alone' 
     AND fd.PaymentMethodID = 0 

это на SQL Server 2005
нет никакой ошибки, а верхний оператор будет возвращать только 1 или нулевой
в то время как нижний оператор возвращает фактическое число найдено.

+0

Какой двигатель, и есть ли какие-либо ошибки, пожалуйста? – gbn

+0

Это триггер ON DELETE? – Andomar

+0

Это триггер после обновления. –

ответ

1

схема (или, по крайней мере, как создается вид) будет помогите, но вот догадка ...

Если вы ищете несколько строк в vwFundingDisbursement со значением «Alone» в имени типа распространения, тогда JOIN собирается перенаправить rn несколько строк, так как ваша исходная таблица (INSERTED) объединяется в несколько строк в представлении. Если вы используете IN, хотя SQL не заботится, вернет ли он несколько совпадений, это даст вам только одну строку.

В качестве примера:

CREATE TABLE dbo.Test_In_vs_Join1 
(
    my_id  INT  NOT NULL 
) 

CREATE TABLE dbo.Test_In_vs_Join2 
(
    my_id  INT  NOT NULL 
) 

INSERT INTO dbo.Test_In_vs_Join1 (my_id) VALUES (1) 
INSERT INTO dbo.Test_In_vs_Join1 (my_id) VALUES (2) 
INSERT INTO dbo.Test_In_vs_Join1 (my_id) VALUES (3) 
INSERT INTO dbo.Test_In_vs_Join1 (my_id) VALUES (4) 
INSERT INTO dbo.Test_In_vs_Join1 (my_id) VALUES (5) 

INSERT INTO dbo.Test_In_vs_Join2 (my_id) VALUES (1) 
INSERT INTO dbo.Test_In_vs_Join2 (my_id) VALUES (1) 
INSERT INTO dbo.Test_In_vs_Join2 (my_id) VALUES (2) 
INSERT INTO dbo.Test_In_vs_Join2 (my_id) VALUES (3) 
INSERT INTO dbo.Test_In_vs_Join2 (my_id) VALUES (3) 

SELECT 
    T1.my_id, 
    COUNT(*) 
FROM 
    dbo.Test_In_vs_Join1 T1 
INNER JOIN dbo.Test_In_vs_Join2 T2 ON 
    T2.my_id = T1.my_id 
GROUP BY 
    T1.my_id 

SELECT 
    T1.my_id, 
    COUNT(*) 
FROM 
    dbo.Test_In_vs_Join1 T1 
WHERE 
    T1.my_id IN (SELECT T2.my_id FROM dbo.Test_In_vs_Join2 T2) 
GROUP BY 
    T1.my_id 

На стороне записки, похоронив столбец внутри другого столбца, как это нарушение нормализованной формы и просто просят проблем. Выполнение такого рода бизнес-логики в триггере также является опасным путем, когда вы узнаете об этом.

+0

Я не уверен, что вы имеете в виду, зарывая колонку, но я, безусловно, согласен и понимаю идею не помещать бизнес-логику в базу данных. И мне вообще не нравятся триггеры, но это было не мое решение. –

+0

Это может быть правильное решение; предложение IN не найдет несколько строк в vwFundingDisbursement, но JOIN будет. Похожая колонна, вероятно, является Alone в конце DisbTypeName. Он должен быть его собственной колонкой. – Andomar

+0

То, что я хочу сказать, похоронив столбец, состоит в том, что у вас, похоже, есть столбец символов DisbTypeName, и внутри этого столбца вы храните флаг того, можно ли вставить плату с другими сборами того же типа. –

4

У вас есть значение null vwFundingDisbursement.settlementid? Это появилось недавно?

+0

Нет, это была одна из вещей, на которые я смотрел. Спасибо за ваше время. –

+1

+1 Хорошая точка, «i.id IN (...)» никогда не является истиной, если * any * из строк в подзапросе NULL. Если один поселенец является NULL, даже в течение всего времени обработки, это может привести к сбою. – Andomar

+1

Нет, IN является последовательным ORs и обрабатывает NULL. «NOT IN» не работает для NULL. См. Это http://stackoverflow.com/questions/129077/sql-not-in-constraint-and-null-values ​​ – gbn

0

Количество (*)
счетчик (i.id)

будет возвращать различные счетчики, основанные на NULL значения

In SQL, what’s the difference between count(*) and count('x')?

+0

Но идентификационный столбец вряд ли будет NULL – Andomar

+0

@Andomar, да, дух этого не заметил, пока ты не указал на это. –

0

Я предполагаю, что это MSSQL (?), И он обрабатывает инструкцию UPDATE, поскольку вы соединяете как вставленные/удаленные таблицы?

В какой таблице находится этот триггер?

Смежные вопросы