【问题标题】:Get non existence arguments of SQL IN operator获取 SQL IN 运算符的不存在参数
【发布时间】:2015-02-08 10:18:13
【问题描述】:

我有以下 SQL 查询:

SELECT column FROM table WHERE column IN ('item1','item2','item3')

它的结果包含item1和item2,我怎样才能得到不存在的论点(item3)?
有可能吗?

编辑: 我有一系列项目。每分钟都会有一些新项目添加到数组中。 所以我应该得到表中不存在的新项目。 之后我可以完成我的过程并将新项目插入到表格中

谢谢

【问题讨论】:

  • 什么是non existence argument
  • 你必须清楚这一点。是否要添加带有 item3 的列?
  • @dotnetom 在这个例子中是“item3”
  • 按条件删除第 3 项
  • @ShayanKM 仍然没有解释你的意思是什么?您想添加数据样本和您的预期结果,以便我们了解您想要实现的目标吗?

标签: sql sql-server in-operator


【解决方案1】:

如果您将数组转换为这样的表格,您可以这样做:

Select * From 
( select 'item1' As Column
  union
  select 'item2' As Column
  union
  select 'item3' As Column
) l
left join Table t on l.Column = t.Column
Where t.Column is NULL

没有联合的版本:

Select * From 
    ( VALUES
      ('Item1'),
      ('Item2'),
      ('Item3')  
    ) As l(Column)
    left join Table t on l.Column = t.Column
    Where t.Column is NULL

【讨论】:

  • 它完成了这项工作,但我认为使用“union select”而不是“IN”会影响我的表现......没有其他更好的方法吗?
  • 检查新版本的语句
【解决方案2】:

以下查询将返回 MyTable 中不存在的项目:

WITH B
AS
(
    SELECT 'Item1' AS col
    UNION ALL
    SELECT 'Item2' 
    UNION ALL
    SELECT 'Item3' 

)
SELECT B.col
FROM B
WHERE
    NOT EXISTS (
        SELECT *
        FROM MyTable T
        WHERE
            T.col = B.col
    )

编辑: 由于在客户端构建这样的 select 语句可能很繁琐和危险,您应该注意 sql 注入和格式问题,我建议您使用如下表值函数:

CREATE TABLE Items
(
    item nvarchar(128) PRIMARY KEY
)

GO

CREATE FUNCTION GetNonExistingItems( @Items xml )
RETURNS TABLE
AS RETURN
WITH B
AS
(
    SELECT c.value('.', 'nvarchar(128)') As item
    FROM @items.nodes('items/item') T(c)
)
SELECT B.item
FROM B
WHERE
    NOT EXISTS (
        SELECT *
        FROM Items I
        WHERE B.item = i.item

    )

GO

DECLARE @items XML = N'
<items>
    <item>Item1</item>
    <item>Item2</item>
    <item>Item5</item>
</items>'

SELECT *
FROM GetNonExistingItems (@Items)

【讨论】:

  • 谢谢!它起作用了......它与@Giorgi_Nakeuri 写的有点相似。但我不确定这些查询的性能,这是最好的方法吗?
  • 性能与 LEFT JOIN WHERE MyTable.col IS NULL 相似(如果不等于),
【解决方案3】:

阅读您的编辑后,我可以建议您采用以下方法。因为您想将不存在的项目插入表中,所以我认为您可以在一个合并语句中完成此操作

给定下表:

CREATE TABLE Items
(
    item nvarchar(128) PRIMARY KEY
)

您可以将数组中的新项目以 xml 形式传递给以下存储过程:

CREATE PROCEDURE InsertIfNotExists @Items xml
AS
    WITH B
    AS
    (
        SELECT c.value('.', 'nvarchar(128)') As item
        FROM @items.nodes('items/item') T(c)
    )
    MERGE INTO Items I
    USING B ON B.Item = I.Item
    WHEN NOT MATCHED BY TARGET THEN
    INSERT (Item) VALUES (Item);

GO

这里有一个示例执行:

DECLARE @items XML = N'
<items>
    <item>Item1</item>
    <item>Item2</item>
    <item>Item3</item>
    <item>Item4</item>
</items>'

EXEC InsertIfNotExists @items

将项目传递给存储过程的另一种方法是使用表值参数而不是 xml。

【讨论】:

  • 感谢您对编辑的关注和 +1。但是我在 select 和 insert 查询之间有一个 .NET 进程,所以这些不应该合并。
  • 好的,我编辑了我之前的答案,为您提供我认为更好的方法
【解决方案4】:

创建一个过程来返回所有存在然后做它

SELECT column FROM table WHERE column NOT IN(your proc );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 2013-05-19
    相关资源
    最近更新 更多