SQL JOIN соответствует значениям столбца NULL - PullRequest
0 голосов
/ 05 июля 2018

Я использую JOIN в MS SQL Server 2012 для удаления записей в одной таблице, которые соответствуют записям в другой таблице, используя

DELETE t1
FROM Table1 t1
JOIN Table2 t2
    ON 
    t1.[Column1] = t2.[Column1] 
    AND t1.[Column2] = t2.[Column2] 
    AND t1.[Column3] = t2.[Column3] 

Однако, если столбцы в обеих таблицах содержат null, они не сопоставляются и не удаляются. Как можно изменить запрос, чтобы он соответствовал записям, если оба столбца содержали null, без добавления специальных проверок для null

DELETE t1
FROM Table1 t1
JOIN Table2 t2
    ON 
    t1.[Column1] = t2.[Column1] OR (t1.[Column1] is null and t2.[Column1] is null)
    AND t1.[Column2] = t2.[Column2] OR (t1.[Column2] is null and t2.[Column2] is null)
    AND t1.[Column3] = t2.[Column3] OR (t1.[Column3] is null and t2.[Column3] is null)

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Может быть попробовать следующее:

DELETE t1
FROM Table1 t1
JOIN Table2 t2
    ON 
    Isnull(t1.[Column1],'') = isnull(t2.[Column1],'')
    AND isnull(t1.[Column2],'') = isnull(t2.[Column2],'')
    AND isnull(t1.[Column3],'') = isnull(t2.[Column3],'');
0 голосов
/ 05 июля 2018

Это реальная проблема, потому что SQL Server не имеет NULL -безопасного оператора сравнения. Стандартный оператор ANSI: IS NOT DISTINCT FROM.

Проблема с OR заключается в том, что она исключает использование индексов. Проблема с ISNULL() такая же. Так что, если ваши таблицы имеют какой-либо размер, вы хотите их избежать.

Одна вещь, которую вы можете сделать, это установить значения по умолчанию. Я не знаю, какие значения по умолчанию позволяют избежать существующих значений, но это может выглядеть так:

update table1
    set column1 = coalesce(column1, ''),  -- for strings
        column2 = coalesce(column2, -1),  -- for numbers
        column3 = coalesce(column3, cast('1900-01-01' as date))  -- for dates
    where column1 is null or column2 is null or column3 is null;

Вам нужно будет сделать это на обоих столах. После этого вы можете восстановить значения NULL после удаления.

На самом деле, в SQL Server вы можете добавить вычисляемые столбцы:

alter table1 add column1_notnull as (coalesce(column1, '')) persisted;  -- or whatever

Затем вы можете создать индекс для них:

create index idx_table1_columns_123_notnull on table1(column1_notnull, column2_notnull, column3_notnull);

И повторите для table2.

Тогда ваш первый запрос будет работать (конечно, используя столбцы _notnull) и использовать индекс для производительности.

0 голосов
/ 05 июля 2018

Вы можете использовать SET ANSI_NULLS OFF, чтобы = считал два null с равными.

...