Вставить в таблицу SQL Server, только если некоторые столбцы не дублируются

#sql #sql-server #subquery #sql-insert #bulkinsert

#sql #sql-сервер #Подзапрос #sql-вставка #bulkinsert

Вопрос:

У меня есть таблица SQL Server, подобная этой:

 CREATE TABLE [dbo].[Person]
(
    [ID] [uniqueidentifier] NOT NULL,
    [name] [uniqueidentifier] NOT NULL,
    [address] [nvarchar](50) NULL,
    [value] [nvarchar](max) NULL
    [date] [datetime] NOT NULL,

    CONSTRAINT [PK_Person] 
        PRIMARY KEY CLUSTERED ([ID] ASC)
)
  

В нем есть такие данные, как:

 ID  name   address  value    date
-----------------------------------------------------
1   a      1         10      2020-08-27 06:06:29.833
2   b      2         30      2020-08-28 06:06:29.833
3   c      3         5       2020-08-27 06:06:29.833
4   d      4         30      2020-08-28 06:06:29.833
  

Я делаю массовую вставку в эту таблицу. При вставке я не хочу вставлять, если данные дублируются для (имя, адрес, значение). Я хочу молча вставить данные.

Поэтому, если вводимые данные для вставки являются:

 ID  name   address  value    date
-----------------------------------------------------
5   e      5         10      2020-08-27 06:06:29.833
6   b      2         30      2020-08-29 06:06:29.833
7   c      3         5       2020-08-30 06:06:29.833
8   f      4         30      2020-08-28 06:06:29.833
  

Тогда будут вставлены только строки с идентификаторами 5 и 8, а строки с идентификаторами 6 и 7 будут считаться дублирующимися и не должны вставляться как новые, а итоговая таблица (имя, адрес, значение) всегда уникальна.

Мой плохой. Входные данные поступают не из таблицы. Это список на python.

список = [[‘e’, 5, 10], [‘b’, 2,30], [‘c’, 3, 5], [‘f’, 4,30]]

И в настоящее время мой запрос:

 insert_query = "INSERT INTO Person(ID,name,address,value,date) VALUES ( newID(),%s, %s, %s,getDate());"
cursor.executemany(insert_query, list)

  

Я хочу иметь что-то вроде:

 insert_query = "INSERT INTO Person(ID,name,address,value,date) VALUES ( newID(),%s, %s, %s,getDate()) on duplicate(name,address,value) ignore that insert;"
cursor.executemany(insert_query, list)

  

Комментарии:

1. Пожалуйста, покажите нам свой insert код.

2. Вы что-нибудь пробовали? Проверяли какие-либо другие вопросы SO, искали ответы? Это очень распространенный вопрос, который легко решается с помощью самосоединения или предложения EXISTS. Я заметил по крайней мере один подобный вопрос на этой неделе

3. «в конечной таблице (имя, адрес, значение) всегда уникально». Ну, первое, что я бы сделал, это создал уникальное ограничение (или индекс) для этих столбцов, еще до того, как я перейду к работе со вставками.

4. Но это вызовет ошибку. Я хочу тихую вставку других новых строк, в которых данные не дублируются

Ответ №1:

Если я правильно вас понял, вы можете использовать not exists :

 insert into person (name, address, value, date)
select x.*
from (values (@name, @address, @value, @date)) as x(name, address, value, date)
where not exists (
    select 1
    from person p1
    where p1.name = p.name and p1.address = p.address and p1.value = p.value
)