MS SQL Server使用复合键选择多行

MS SQL Server使用复合键选择多行,sql,sql-server,Sql,Sql Server,我正在尝试编写一个查询,它接受一组salesOrderId+lineNumber组合,并在单个查询中返回该组合。我可以轻松地使用每次选择一行,其中。。。在…语法中(见下文),但由于我有一个复合键,所以我不确定如何使用它 使用SQL Server,有哪些方法可以选择多行 此查询将支持与以下类似的函数: getSalesOrderLines([ { SalesOrder: "C1001115", SalesOrderLine: 1 }, { SalesOrder: "C1001115",

我正在尝试编写一个查询,它接受一组salesOrderId+lineNumber组合,并在单个查询中返回该组合。我可以轻松地使用
每次选择一行,其中。。。在…
语法中(见下文),但由于我有一个复合键,所以我不确定如何使用它

使用SQL Server,有哪些方法可以选择多行

此查询将支持与以下类似的函数:

getSalesOrderLines([ 
  { SalesOrder: "C1001115", SalesOrderLine: 1 }, 
  { SalesOrder: "C1001115", SalesOrderLine: 3 },
  { SalesOrder: "C1001222", SalesOrderLine: 1 } 
])
应该返回如下内容:

[
  { SalesOrder: 'C1001115', SalesOrderLine: 1, ... },
  { SalesOrder: 'C1001115', SalesOrderLine: 3, ... }
  { SalesOrder: 'C1001222', SalesOrderLine: 1, ... }
]
工作:选择一行:

SELECT *
FROM [SalesOrderDetailDetail]
WHERE [SalesOrderDetailDetail].[SalesOrder] = 'C1001115'
  AND [SalesOrderDetailDetail].[SalesOrderLine] = 1
不工作:元组比较/行构造函数

SELECT *
FROM [SalesOrderDetail]
WHERE ([SalesOrderDetail].[SalesOrder], 
       [SalesOrderDetail].[SalesOrderLine]) 
   IN (('C1001115', 1))
这会引发一个错误:

在需要条件的上下文中指定的非布尔类型的表达式

不工作:派生密钥:

SELECT 
    [SalesOrderDetail].[SalesOrder] + '-' + CAST([SalesOrderDetail]. [SalesOrderLine] AS VARCHAR) AS [comboKey],
    *
FROM [SalesOrderDetail]
WHERE comboKey IN (('C1001115-1'))

但是我了解到不能在
WHERE
子句中直接使用列别名,可以通过两种不同的方式实现

您可以像第一次尝试使用combokey字符串值一样执行此操作。是的,您是对的,您不能在where语句中使用别名,但可以在where语句中对表达式求值

SELECT 
  [SalesOrderDetail].[SalesOrder] + '-' + CAST([SalesOrderDetail]. [SalesOrderLine] AS VARCHAR) AS [comboKey],
  *
FROM [SalesOrderDetail]
WHERE ([SalesOrderDetail].[SalesOrder] + '-' + CAST([SalesOrderDetail]. [SalesOrderLine]) IN (('C1001115-1')
或者,您可以使用多个Or语句来获得所需的结果集

SELECT *
FROM [SalesOrderDetail]
WHERE ([SalesOrderDetail].[SalesOrder] = 'C1001115' AND [SalesOrderDetail].SalesOrderLine] = 1) 
OR ([SalesOrderDetail].[SalesOrder] = 'C1001115' AND [SalesOrderDetail].SalesOrderLine] = 3) 

一种方法使用
交叉连接

SELECT *
FROM SalesOrderDetail sod CROSS JOIN
     (VALUES ('C1001115', 1)) v(SalesOrder, SalesOrderLine)
     ON v.SalesOrder = sod.SalesOrder AND
        v.SalesOrderLine = sod.SalesOrderLine;

您可以向
VALUES()
列表中添加更多对,最多可添加任意数。

您可以在CTE或子查询中创建一个表,然后加入到该表中

WITH selList as (
Select 'C1001115' as SalesOrder, 1 as SalesOrderLine
UNION ALL Select 'C1001115', 3
UNION ALL Select 'C1001222', 1
)
SELECT D.*
FROM [SalesOrderDetailDetail] D
    INNER JOIN selList L on L.SalesOrder = D.SalesOrder and L.SalesOrderLine = D.SalesOrderLine

如上所述,在编写直接查询时,这是很笨拙的。但是,如果要创建存储过程,可以删除选择列表创建,并将所需的行键作为TVP(表值参数)传递给存储过程。根据您从何处获取选择详细信息,这可能是您最容易做到的事情,特别是当您可能有大量行要选择时-您不需要更改SQL,只需给它一个键列表即可


您将需要查找TVP,但简而言之,您将使用键列创建一个用户定义的表类型,然后您的存储过程将具有该类型的只读参数,并且存储过程中的查询将连接到该参数以供选择。当您调用SP时,您会将选择数据作为表格传递。

我的答案与其他答案略有不同。这涉及到应用程序开发人员和数据开发人员之间的一些协调

您说过希望查询支持此函数:

getSalesOrderLines([ 
  { SalesOrder: "C1001115", SalesOrderLine: 1 }, 
  { SalesOrder: "C1001115", SalesOrderLine: 3 },
  { SalesOrder: "C1001222", SalesOrderLine: 1 } 
])
这恰好看起来很像JSON。我知道可能不是这样,但问题是,如果你可以让应用程序以JSON(读:
NVARCHAR(MAX)
)字符串的形式向你发送数据,并且你使用的是SQL 2016或更高版本,那么你就可以利用SQL Server中本机JSON的强大功能

但首先,让我们制作一个示例orders表,并用一些测试数据填充它:

CREATE TABLE #SalesOrderDetail
(
    SalesOrder VARCHAR(10),
    SalesOrderLine INT,
    ItemNumber INT
)
INSERT INTO #SalesOrderDetail
(
    SalesOrder
    ,SalesOrderLine
    ,ItemNumber
)
VALUES
('C1001115', 1, 100),
('C1001115', 2, 200),
('C1001115', 3, 300),
('C1001222', 1, 9832475),
('C1001222', 2, 634),
('C1001222', 3, 73546)
接下来,假设您的查询将位于存储的proc中,并且proc有一个名为
@ParamJSON
的输入参数。我不想为这个示例编写proc,所以请允许我声明参数的一个版本:

DECLARE @ParamJSON NVARCHAR(MAX) = N'
[
  { "SalesOrder": "C1001115", "SalesOrderLine": 1 },
  { "SalesOrder": "C1001115", "SalesOrderLine": 3 },
  { "SalesOrder": "C1001222", "SalesOrderLine": 1 } 
]'
最后,我们将使用
OPENJSON()
分解JSON,然后加入我们的销售表:

SELECT 
    s.*
FROM OPENJSON(@ParamJSON) 
WITH (
        SalesOrder varchar(10) '$.SalesOrder',
        SalesOrderLine int '$.SalesOrderLine'
    ) p
INNER JOIN #SalesOrderDetail s ON s.SalesOrder = p.SalesOrder AND s.SalesOrderLine = p.SalesOrderLine
这将产生以下结果集:

SalesOrder  | SalesOrderLine    | ItemNumber
------------|-------------------|-----------
C1001115    | 1                 | 100
C1001115    | 3                 | 300
C1001222    | 1                 | 9832475
整洁,对吗?我们甚至可以按照您的要求格式化结果,将整个结果集转换为JSON。只需在SELECT语句末尾添加JSON AUTO的
,如下所示:

SELECT 
    s.*
FROM OPENJSON(@ParamJSON) 
WITH (
        SalesOrder varchar(10) '$.SalesOrder',
        SalesOrderLine int '$.SalesOrderLine'
    ) p
INNER JOIN #SalesOrderDetail s ON s.SalesOrder = p.SalesOrder AND s.SalesOrderLine = p.SalesOrderLine
FOR JSON AUTO 
该查询的结果将是一个JSON格式的字符串,如下所示(为了可读性增加了额外的空白):


您试图检索的结果集是否可能重复?i、 e.销售订单的所有详细信息?。。。。
SELECT 
    s.*
FROM OPENJSON(@ParamJSON) 
WITH (
        SalesOrder varchar(10) '$.SalesOrder',
        SalesOrderLine int '$.SalesOrderLine'
    ) p
INNER JOIN #SalesOrderDetail s ON s.SalesOrder = p.SalesOrder AND s.SalesOrderLine = p.SalesOrderLine
FOR JSON AUTO 
[
 {"SalesOrder":"C1001115","SalesOrderLine":1,"ItemNumber":100}, 
 {"SalesOrder":"C1001115","SalesOrderLine":3,"ItemNumber":300},
 {"SalesOrder":"C1001222","SalesOrderLine":1,"ItemNumber":9832475}
]