【问题标题】:How to pass parameter into WITH clause Where Statement?如何将参数传递给 WITH 子句 Where 语句?
【发布时间】:2015-10-02 14:53:56
【问题描述】:

如何使用在代码中为粗体的 with 子句中的 where 语句中包含字符串的参数。我尝试使用该方法,但它不起作用。

我已经添加了一个名为 @param nvarchar(max) 的参数。

WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
(
    SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
    FROM Sales.SalesOrderHeader
    **WHERE SalesPersonID IN ('+ @param +')**
)
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID

【问题讨论】:

  • 您有 2 个选择,1. 使用动态 SQL,2,将 LIKE 与 @param 的已知模式一起使用
  • 动态sql怎么做?我尝试在 with 子句中使用 SET @sql = 'Select.......' 但我不认为它真的有效。你能告诉我如何用你的方式使用动态 sql 吗?
  • 理想情况下,更改您的调用约定。使用 xml,或者,理想情况下,使用表值参数,而不是 字符串。前两种类型都设计用于保存多个值,并且可以(相对)自然地在查询中使用。一个字符串(我猜这将是一个包含逗号和可能的引号的字符串)将被视为单个字符串,就像在大多数其他语言中一样。
  • 如果@param 像'1,2,3'或'1',你可以轻松创建where条件,无需动态SQLWHERE ',' + @param + ',' LIKE '%,' + CAST(SalesPersonID as varchar(10)) + ',%'
  • @param 将类似于“'ID 21312','ID 1243213','ID 342342'.......”类似的东西

标签: sql sql-server-2008


【解决方案1】:

您必须使用 table 变量而不是 NVARCHAR,例如:

DECLARE @param TABLE (id int)
INSERT INTO @param VALUES (1), (2), (3)

;WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
(
    SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
    FROM Sales.SalesOrderHeader
    WHERE SalesPersonID IN (SELECT id FROM @param)
)
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID

或者,如果@param 是逗号分隔的数字列表,您可以使用拆分字符串函数。然后你可以像这样使用IN 运算符:

WHERE SalesPersonID IN (SELECT id FROM dbo.fnSplitString(@param, ',') 

Here 是关于拆分字符串函数的一个很好的参考。

【讨论】:

    【解决方案2】:
    Declare @param varchar(max) = 'some value'
    
    ;WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
    AS
    (
        SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
        FROM Sales.SalesOrderHeader
        WHERE SalesPersonID IN (''+ @param +'')
    )
    SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
    FROM Sales_CTE
    GROUP BY SalesYear, SalesPersonID
    

    或者你可以实现这个动态查询

    【讨论】:

    • 您好,感谢您的回复。但我确实收到错误:在 data adapter.fill(dataset) 行中从字符串错误转换日期和/或时间时转换失败,因为参数由字符串组成。
    【解决方案3】:

    正如乔纳森所说,您可以在此处使用动态查询,如下所述。

    DECLARE @param VARCHAR(MAX)
    DECLARE @query NVARCHAR(MAX)
    
    SET @param = '1,2,5'
    
    SET @query  = 'WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
    AS
    (
       SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
       FROM Sales.SalesOrderHeader
       WHERE SalesPersonID IN ('+ @param +')
     )
     SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
     FROM Sales_CTE
     GROUP BY SalesYear, SalesPersonID'
    
     EXEC SP_EXECUTESQL @query
    

    【讨论】:

    • 我现在主要担心的是,如果我将整个语句放入其中,我的 WITH 子句相当长,超过 4000 个字符。请指教。
    • NVARCHAR(MAX) 类型的列的最大大小为 2 GB 的存储空间。因此,在您的情况下,如果参数大小要大得多,那么您还必须将 param 声明为 NVARCHAR(max)。
    • @J-D - 一个nvarchar(max) 变量可以存储more than 2GB。 2GB 限制适用于
    • 是不是受SET @QUERY = ' ' 的字符数限制?是按尺寸计算的吗?
    • @newtoasp - 不是这样concatenating multiple strings together though时你要小心:“如果字符串拼接的结果超过8000字节的限制,结果会被截断。但是,如果拼接的字符串至少有一个是大值类型,截断不会发生。”
    【解决方案4】:

    可以将查询改为字符串查询,然后执行。

        DECLARE @SQLQuery VARCHAR(MAX)
    
        SET @SQLQuery = 'WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
        AS
        (
            SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
            FROM Sales.SalesOrderHeader
            WHERE SalesPersonID IN (' + @param + ')
        )
        SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
        FROM Sales_CTE
        GROUP BY SalesYear, SalesPersonID'
    
        EXEC(@SQLQuery)
    

    【讨论】:

    • 嗨,由于参数包含一个字符串,它不起作用,谢谢。在数据适配器填充(数据集)行期间从字符串错误转换日期和/或时间时转换失败。
    • @newtoasp 我将答案修改为字符串 sql 查询,我认为这是实现您想要的更好的方法。
    • 关键字“WITH”附近出现语法错误。请指教谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2016-03-26
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多