【问题标题】:SQL Function Throws Type Error When Passing in ParamsSQL 函数在传入参数时抛出类型错误
【发布时间】:2019-07-13 01:54:30
【问题描述】:

该函数正在寻求返回一个整数值,该整数值等于列中出现在零之前的值的总和,并将其添加到列中的最终值。

CREATE FUNCTION name
     (@p1 NVARCHAR(MAX),
      @p2 INT, 
      @p3 INT)
RETURNS INT
AS 
BEGIN
    DECLARE @total INT = 0
    DECLARE @cnt INT = 1;
    DECLARE @row INT = 0
    DECLARE @nextRow INT = 0;
    DECLARE @tmp NVARCHAR(MAX)

    SET @tmp = @p1

    DECLARE @myTemp TABLE (Col INT, ID1 INT, ID2 INT, reading NVARCHAR(MAX));
    DECLARE @zeroCols TABLE(rn INT, Col INT);


    INSERT INTO @myTemp
        SELECT ROW_NUMBER() OVER(ORDER BY nHeatID) Col, col2, col3, @tmp 
        FROM schema.table
        WHERE col4 = @p2 
          AND col5 = @p3

    SET @total = (SELECT TOP 1 @tmp FROM @myTemp ORDER BY col DESC)

    INSERT INTO @zeroCols
        SELECT ROW_NUMBER() OVER(ORDER BY col) rn, col  
        FROM @myTemp 
        WHERE @tmp = 0

        WHILE @cnt <= (SELECT COUNT(Col) FROM @zeroCols)
        BEGIN
            SET @row = (SELECT Col FROM @zeroCols WHERE rn = @cnt)

            IF ((SELECT @tmp FROM @myTemp WHERE col = @row-1) <> 0)
                SET @total = @total + (SELECT @tmp FROM @myTemp WHERE col = @row-1); 

            SET @cnt = @cnt + 1;
        END;

        RETURN @total
END;

@myTemp 表将我的表中的数据与行号放在一起,@zeroCols 表将行号放在零所在的位置。

然后我遍历该组值并确定在提供的列的零之前是否有一个非零值,如果有,我将其添加到总数中。

这在我尝试将它变成一个函数之前就已经奏效了。

难道不喜欢我将nvarchar 作为列名传递吗?

当我这样称呼它时:

SELECT name('val', 0, 0)

我收到此错误:

将 nvarchar 值 'val' 转换为数据类型 int 时转换失败

【问题讨论】:

  • 我们在这里遗漏了真正重要的部分...函数的 DDL。
  • 欢迎来到 SO。如果您提供代码肯定会有所帮助。显然,您在代码中的某处使用了@p1,它被转换(可能是隐式地)转换为 int。注意 int 的优先级比 text 高,所以如果你把它和其他 int 的地方混在一起,它会尝试改变它。通常在您尝试打印某些内容时发生。
  • 错误在...function body...。我们需要看到那部分。
  • 问题不在于将'val'强制转换为nvarchar(max)的参数数据类型,问题是在@p1作为int内部使用功能体。我敢打赌,如果你传递值 '1' 而不是 'val' 你不会得到错误。
  • 当一些没有经验的开发人员尝试将具有 int 数据类型的列/变量与列/变量/硬编码的 varchar/nvarchar 进行比较时,会发生 100 次中的 99 次。原因是 SQL Server 会尝试将字符串值隐式转换为 int 值。没有看到函数的代码,不可能给出更准确的答案。

标签: sql sql-server tsql


【解决方案1】:

我已将问题简化为:

@p1 nvarchar(max) -- Parameter of the function

--...

DECLARE @total INT = 0
DECLARE @tmp nvarchar(max)
SET @tmp = @p1

--...

DECLARE @myTemp TABLE(Col INT, ID1 INT, ID2 INT, reading nvarchar(max));

--...

SET @total = (SELECT TOP 1 @tmp FROM @myTemp ORDER BY col DESC) -- Can't convert property

您将@tmp (NVARCHAR(MAX)) 的值分配给@total,这是一个INT

我无法推断您要对此做什么,因此我无法提出修复建议,只需确保分配匹配的数据类型即可。

【讨论】:

  • 我没看到,但我确实看到了你在下一个声明中遗漏的问题 - 所以我想我们是平的 :-)
  • 我正在尝试使用作为@p1 传入的值作为行中的列名。如果变量正确地表达了查询,它将评估为 int。
  • 您不能使用变量来引用对象名称(如表、列等)。为此,您必须使用动态 SQL,并且不能在函数中使用动态 SQL。为此,您必须使用 SP。
  • @EzLo 谢谢,我不知道。我希望在 sproc 中引用这个函数,这样它就不会让它变得更乱,但我想我可以使用我的非函数内联
【解决方案2】:

我发现如果我使用开关,那么我可以根据参数决定列名。

Can I pass column name as input parameter in SQL stored Procedure

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多