访问传递查询将逗号分隔列表作为参数传递给 SQL 存储过程
Access pass-through query passing comma separated list as a parameter to SQL stored procedure
SQL 服务器是 2008。我有一个用于报告目的的 Access 2016 前端。一份报告要求从列表中选择一个或多个产品 类 进行报告。我有 VBA 使用适当的单行创建传递查询:
exec dbo.uspINVDAYS 'A3,A4,A6,AA,AB'
我有这个 SQL 代码,应该将列表作为硬编码在这里:
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
DECLARE @DAYS INT,@numDAYS int;
SET @DAYS = 395;
SET @numDAYS = @DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,@numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass IN (Select val From TablesCoE.dbo.split(@ProductClasses,','));
当我 运行 我得到:
Msg 468, Level 16, State 9, Line 9
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_BIN" in the equal to operation.
我无法确定位置
COLLATE SQL_Latin1_General_CP1_CI_AS
该走了。我在哪里等同或比较? SQL IN 子句无法处理逗号分隔的列表,因为它不是严格的 SQL table.
这是用于创建 dbo.split() 函数的代码:
CREATE FUNCTION dbo.split(
@delimited NVARCHAR(MAX),
@delimiter NVARCHAR(100)
) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE @xml XML
SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
INSERT INTO @t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM @xml.nodes('/t') as records(r)
RETURN
END
感谢 Sandeep Mittal,我相信其他人也有非常相似的拆分功能。 运行 此函数确实按预期运行并提供 table 逗号分隔列表对象。
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
Select val From TablesCoE.dbo.split(@ProductClasses,',')
Returns
val
A3
A4
A6
AA
AB
试试这个。
WHERE concat(',',@ProductClasses,',') like concat('%',UPINVENTORY.ProductClass,'%')
这是一种检查 productClass
是否在 @productClasses
列表中的愚蠢方法。
在尝试使用预制的 table 值变量与 WHERE 子句中的动态变量之后,两者都不起作用,然后我开始尝试 COLLATE 语句的不同位置。我很自满地将 COLLATE 应用到右侧,并在 SQL 错误消息的左侧列出了排序规则。我尝试了 WHERE 子句左侧 SQL 错误消息右侧列出的排序规则,现在 SQL 代码符合规范。这是:
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
DECLARE @DAYS INT,@numDAYS int;
SET @DAYS = 395;
SET @numDAYS = @DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,@numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass COLLATE Latin1_General_BIN IN (SELECT val FROM TablesCoE.dbo.split(@ProductClasses,','));
感谢@Krish 和@Isaac 的建议。
蒂姆
SQL 服务器是 2008。我有一个用于报告目的的 Access 2016 前端。一份报告要求从列表中选择一个或多个产品 类 进行报告。我有 VBA 使用适当的单行创建传递查询:
exec dbo.uspINVDAYS 'A3,A4,A6,AA,AB'
我有这个 SQL 代码,应该将列表作为硬编码在这里:
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
DECLARE @DAYS INT,@numDAYS int;
SET @DAYS = 395;
SET @numDAYS = @DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,@numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass IN (Select val From TablesCoE.dbo.split(@ProductClasses,','));
当我 运行 我得到:
Msg 468, Level 16, State 9, Line 9
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_BIN" in the equal to operation.
我无法确定位置
COLLATE SQL_Latin1_General_CP1_CI_AS
该走了。我在哪里等同或比较? SQL IN 子句无法处理逗号分隔的列表,因为它不是严格的 SQL table.
这是用于创建 dbo.split() 函数的代码:
CREATE FUNCTION dbo.split(
@delimited NVARCHAR(MAX),
@delimiter NVARCHAR(100)
) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE @xml XML
SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
INSERT INTO @t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM @xml.nodes('/t') as records(r)
RETURN
END
感谢 Sandeep Mittal,我相信其他人也有非常相似的拆分功能。 运行 此函数确实按预期运行并提供 table 逗号分隔列表对象。
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
Select val From TablesCoE.dbo.split(@ProductClasses,',')
Returns
val
A3
A4
A6
AA
AB
试试这个。
WHERE concat(',',@ProductClasses,',') like concat('%',UPINVENTORY.ProductClass,'%')
这是一种检查 productClass
是否在 @productClasses
列表中的愚蠢方法。
在尝试使用预制的 table 值变量与 WHERE 子句中的动态变量之后,两者都不起作用,然后我开始尝试 COLLATE 语句的不同位置。我很自满地将 COLLATE 应用到右侧,并在 SQL 错误消息的左侧列出了排序规则。我尝试了 WHERE 子句左侧 SQL 错误消息右侧列出的排序规则,现在 SQL 代码符合规范。这是:
DECLARE @parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE @ProductClasses NVARCHAR(200),@delimiter NVARCHAR(1) = ',';
SET @ProductClasses = @parProductClasses;
DECLARE @DAYS INT,@numDAYS int;
SET @DAYS = 395;
SET @numDAYS = @DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,@numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/@DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass COLLATE Latin1_General_BIN IN (SELECT val FROM TablesCoE.dbo.split(@ProductClasses,','));
感谢@Krish 和@Isaac 的建议。 蒂姆