首页 文章

SQL Server插入(如果不存在)

提问于
浏览
139

我想在我的表中插入数据,但只插入我的数据库中不存在的数据!

这是我的代码:

ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
  (@_DE nvarchar(50),
   @_ASSUNTO nvarchar(50),
   @_DATA nvarchar(30) )
AS
BEGIN
   INSERT INTO EmailsRecebidos (De, Assunto, Data)
   VALUES (@_DE, @_ASSUNTO, @_DATA)
   WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos 
                   WHERE De = @_DE
                   AND Assunto = @_ASSUNTO
                   AND Data = @_DATA);
END

错误是:

消息156,级别15,状态1,过程EmailsRecebidosInsert,第11行关键字'WHERE'附近的语法不正确 .

9 回答

  • 7

    试试下面的代码

    ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
      (@_DE nvarchar(50),
       @_ASSUNTO nvarchar(50),
       @_DATA nvarchar(30) )
    AS
    BEGIN
       INSERT INTO EmailsRecebidos (De, Assunto, Data)
       select @_DE, @_ASSUNTO, @_DATA
       EXCEPT
       SELECT De, Assunto, Data from EmailsRecebidos
    END
    
  • 213

    而不是代码

    BEGIN
       INSERT INTO EmailsRecebidos (De, Assunto, Data)
       VALUES (@_DE, @_ASSUNTO, @_DATA)
       WHERE NOT EXISTS ( SELECT * FROM EmailsRecebidos 
                       WHERE De = @_DE
                       AND Assunto = @_ASSUNTO
                       AND Data = @_DATA);
    END
    

    用 . . . 来代替

    BEGIN
       IF NOT EXISTS (SELECT * FROM EmailsRecebidos 
                       WHERE De = @_DE
                       AND Assunto = @_ASSUNTO
                       AND Data = @_DATA)
       BEGIN
           INSERT INTO EmailsRecebidos (De, Assunto, Data)
           VALUES (@_DE, @_ASSUNTO, @_DATA)
       END
    END
    

    Updated : (感谢@Marc Durdin指点)

    请注意,在高负载下,这仍然有时会失败,因为第二个连接可以在第一个连接执行INSERT之前通过IF NOT EXISTS测试,即竞争条件 . 请参阅stackoverflow.com/a/3791506/1836776以获得有关为什么即使在事务中包装也无法解决此问题的答案 .

  • 9

    对于那些寻找最快速方式的人来说,我最近came across these benchmarks显然使用"INSERT SELECT... EXCEPT SELECT..."成为5000万或更多记录中最快的 .

    这是文章中的一些示例代码(第3块代码是最快的):

    INSERT INTO #table1 (Id, guidd, TimeAdded, ExtraData)
    SELECT Id, guidd, TimeAdded, ExtraData
    FROM #table2
    WHERE NOT EXISTS (Select Id, guidd From #table1 WHERE #table1.id = #table2.id)
    -----------------------------------
    MERGE #table1 as [Target]
    USING  (select Id, guidd, TimeAdded, ExtraData from #table2) as [Source]
    (id, guidd, TimeAdded, ExtraData)
        on [Target].id =[Source].id
    WHEN NOT MATCHED THEN
        INSERT (id, guidd, TimeAdded, ExtraData)
        VALUES ([Source].id, [Source].guidd, [Source].TimeAdded, [Source].ExtraData);
    ------------------------------
    INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)
    SELECT id, guidd, TimeAdded, ExtraData from #table2
    EXCEPT
    SELECT id, guidd, TimeAdded, ExtraData from #table1
    ------------------------------
    INSERT INTO #table1 (id, guidd, TimeAdded, ExtraData)
    SELECT #table2.id, #table2.guidd, #table2.TimeAdded, #table2.ExtraData
    FROM #table2
    LEFT JOIN #table1 on #table1.id = #table2.id
    WHERE #table1.id is null
    
  • 6

    我会使用合并:

    create PROCEDURE [dbo].[EmailsRecebidosInsert]
      (@_DE nvarchar(50),
       @_ASSUNTO nvarchar(50),
       @_DATA nvarchar(30) )
    AS
    BEGIN
       with data as (select @_DE as de, @_ASSUNTO as assunto, @_DATA as data)
       merge EmailsRecebidos t
       using data s
          on s.de = t.de
         and s.assunte = t.assunto
         and s.data = t.data
        when not matched by target
        then insert (de, assunto, data) values (s.de, s.assunto, s.data);
    END
    
  • 21

    INSERT 命令没有 WHERE 子句 - 您必须像这样编写它:

    ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
      (@_DE nvarchar(50),
       @_ASSUNTO nvarchar(50),
       @_DATA nvarchar(30) )
    AS
    BEGIN
       IF NOT EXISTS (SELECT * FROM EmailsRecebidos 
                       WHERE De = @_DE
                       AND Assunto = @_ASSUNTO
                       AND Data = @_DATA)
       BEGIN
           INSERT INTO EmailsRecebidos (De, Assunto, Data)
           VALUES (@_DE, @_ASSUNTO, @_DATA)
       END
    END
    
  • 42

    我用SQL SERVER 2012做了同样的事情并且它起作用了

    Insert into #table1 With (ROWLOCK) (Id, studentId, name)
    SELECT '18769', '2', 'Alex'
    WHERE not exists (select * from #table1 where Id = '18769' and studentId = '2')
    
  • 0

    除了IF EXISTS之外,您还可以使用MERGE,具体取决于您的SQL Server版本(2012?):

    ALTER PROCEDURE [dbo].[EmailsRecebidosInsert]
        ( @_DE nvarchar(50)
        , @_ASSUNTO nvarchar(50)
        , @_DATA nvarchar(30))
    AS BEGIN
        MERGE [dbo].[EmailsRecebidos] [Target]
        USING (VALUES (@_DE, @_ASSUNTO, @_DATA)) [Source]([De], [Assunto], [Data])
             ON [Target].[De] = [Source].[De] AND [Target].[Assunto] = [Source].[Assunto] AND [Target].[Data] = [Source].[Data]
         WHEN NOT MATCHED THEN
            INSERT ([De], [Assunto], [Data])
            VALUES ([Source].[De], [Source].[Assunto], [Source].[Data]);
    END
    
  • 0

    您可以使用GO命令 . 这将在发生错误后重新启动sql语句的执行 . 在我的情况下,我有几个1000 INSERT语句,其中少数这些记录已存在于数据库中,我只是不知道哪些 . 我发现在处理了几个100之后,执行只是因为记录已经存在而无法INSERT的错误消息而停止 . 相当讨厌,但是把GO解决了这个问题 . 它可能不是最快的解决方案,但速度不是我的问题 .

    GO
    INSERT INTO mytable (C1,C2,C3) VALUES(1,2,3)
    GO
    INSERT INTO mytable (C1,C2,C3) VALUES(4,5,6)
     etc ...
    
  • 17

    As explained in below code: 执行以下查询并验证自己(它们是不言自明的)

    CREATE TABLE `table_name` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(255) NOT NULL,
      `address` varchar(255) NOT NULL,
      `tele` varchar(255) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB;
    

    插入记录:

    INSERT INTO table_name (name, address, tele)
    SELECT * FROM (SELECT 'Nazir', 'Kolkata', '033') AS tmp
    WHERE NOT EXISTS (
        SELECT name FROM table_name WHERE name = 'Nazir'
    ) LIMIT 1;
    Query OK, 1 row affected (0.00 sec)
    Records: 1 Duplicates: 0 Warnings: 0
    
    SELECT * FROM `table_name`;
    
    +----+--------+-----------+------+
    | id | name   | address   | tele |
    +----+--------+-----------+------+
    |  1 | Nazir  | Kolkata   | 033  |
    +----+--------+-----------+------+
    

    现在,尝试再次插入相同的记录:

    INSERT INTO table_name (name, address, tele)
    SELECT * FROM (SELECT 'Nazir', 'Kolkata', '033') AS tmp
    WHERE NOT EXISTS (
        SELECT name FROM table_name WHERE name = 'Nazir'
    ) LIMIT 1;
    
    Query OK, 0 rows affected (0.00 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    +----+--------+-----------+------+
    | id | name   | address   | tele |
    +----+--------+-----------+------+
    |  1 | Nazir  | Kolkata   | 033  |
    +----+--------+-----------+------+
    

    插入不同的记录:

    INSERT INTO table_name (name, address, tele)
    SELECT * FROM (SELECT 'Santosh', 'Kestopur', '044') AS tmp
    WHERE NOT EXISTS (
        SELECT name FROM table_name WHERE name = 'Santosh'
    ) LIMIT 1;
    
    Query OK, 1 row affected (0.00 sec)
    Records: 1 Duplicates: 0 Warnings: 0
    
    SELECT * FROM `table_name`;
    
    +----+--------+-----------+------+
    | id | name   | address   | tele |
    +----+--------+-----------+------+
    |  1 | Nazir  | Kolkata   | 033  |
    |  2 | Santosh| Kestopur  | 044  |
    +----+--------+-----------+------+
    

相关问题