【问题标题】:insert into table and skip duplicates插入表格并跳过重复项
【发布时间】:2015-09-28 09:03:57
【问题描述】:

我的存储过程有 3 个参数,我正在传递 (@nameP, @idP, @dateP) 并将数据插入#myTemp 表中

然后我用

 select * 
    into dbo.realTable
    from #myTemp

然后我想根据datePidP 过滤掉任何已经存在的数据(在dbo.FinalTable 中):

insert into dbo.FinalTable 
select * from dbo.realTable
where not exists (select * from dbo.FinalTable
where idP = @idP
and dateP = @dateP)

drop table dbo.realTable

当我执行我的程序时,数据被附加到表中。问题是如果我输入相同的idP 并为相同的dateP 再次执行它,它不应该插入任何东西,但它会插入。我认为问题可能出在insert into 部分。

编辑:

如果我从 where 子句中删除 and dateP = @dateP,这将非常有效) ps:谢谢大家的回答,即使在我的情况下我只需要做我上面写的,我从你的回答中学到了

【问题讨论】:

  • 查看MERGE 命令。另一点可能是SELECT DISTINCT。广告请提供示例数据和预期输出,
  • 当我运行你的代码时它不会插入第二次。
  • @name 没有在任何地方提及。那是怎么用的?
  • @name 实际上是我正在连接的链接数据库

标签: sql sql-server stored-procedures sql-server-2012


【解决方案1】:

这会插入 realtable do finaltable 中的所有行,其中不存在 idP 和 dateP 的组合...(使用简单的左连接):

INSERT INTO dbo.FinalTable 
SELECT * 
FROM    dbo.RealTable R
        LEFT JOIN dbo.FinalTable T ON T.idP = R.idP 
        AND T.dateP = R.dateP
WHERE T.idP IS NULL

我强烈建议使用列名而不是“*”!

INSERT INTO table (column1, column2)
SELECT column1, column2 FROM anothertable

【讨论】:

  • 我使用 * 因为我有很多列。我会在一分钟内测试你的代码。谢谢
  • 这将添加其他日期的数据,如果同一天有匹配的话。您也忽略了使用参数。
【解决方案2】:

基本上你已经使用了not exists,这是绝对正确的。您下次查询的问题是@dateP。如果您传递相同的@idP 但不同的@dateP 则创建相同的@idp,因为您将针对@idp 和@dateP 进行验证。那么如何保护它,请考虑您的业务场景是否重复,仅适用于 @idp@idp@datep,如果两者都是正确的,但如果只有 @idp,则必须删除 @987654331 @ 来自您的 where 子句。

【讨论】:

  • 谢谢。为了解决它,我不得不从 where 子句中删除 @dateP。做到了!
【解决方案3】:

合并语句是实现这一目标的最有效方法

MERGE dbo.FinalTable  AS TARGET 
USING dbo.RealTable AS SOURCE ON TARGET.idP = SOURCE.idP AND TARGET.dateP = SOURCE.dateP
WHEN NOT MATCHED THEN 
INSERT 
(
name
,idp
,datep
)
VALUES
(
 SOURCE.name
,SOURCE.idp
,SOURCE.datep

);

【讨论】:

  • 你没有提到参数
  • 这看起来是个坏主意,但性能不是很好,是吗?我的程序在 40 秒 - 1 分钟内导出数据。当我添加这部分时,它需要更长的时间。 6 分钟后我停止了它,因为我不应该长时间查询服务器
  • 在第一条评论中想说“看起来是个好主意”。再试一次,大约 10 分钟就停止了
  • 每次执行我有 19 列和 @ 180.000-190.000 行
  • 目标连接列上的非聚集索引可以显着提高性能。
【解决方案4】:

首先,不要在过程中创建表只是为了稍后再删除它。如果多次调用该过程,这可能会导致问题。

您已经有一个可以使用的临时表。

您的代码失败,因为您获取所有行或没有行。您尚未正确加入:

not exists (select * from dbo.FinalTable
where idP = @idP
and dateP = @dateP)

试试这个instread:

INSERT dbo.FinalTable -- (you should name columns instead of using wildchar)
SELECT *
FROM dbo.realTable rt
WHERE
  not exists
  (
    SELECT *
    FROM dbo.FinalTable ft
    WHERE
      rt.idP = idP
      and **rt**.dateP = **ft**.dateP
      )
  and 
    idP = @idP
  and
    dateP = @dateP

【讨论】:

  • 谢谢,将测试您的解决方案。我正在命名列,只是更改了名称以便能够在此处发布\
  • 你想在第一行写上insert into dbo.FinalTable,对吧?
  • 试过你的代码,起初很高兴它可以工作。然后留下nameP一样,dateP一样,改了idP。如果我再次执行它,它不会插入任何其他内容。因为它是一个不同的id,所以所有这些字段都应该被插入
猜你喜欢
  • 2023-03-13
  • 2020-08-12
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 2014-12-03
  • 1970-01-01
  • 2015-01-13
相关资源
最近更新 更多