在没有引号的函数中传递值 T-SQL / SQL Server 2012?

Passing value in a function without quote T-SQL / SQL Server 2012?

我在 SQL Server 2012 中创建的一个函数需要帮助,该函数用于检查输入值。如果函数检测到数字 - return 0,如果检测到字符 return 1.

但是对于同一个数字,我得到了 2 个不同的结果,有引号和没有引号。

select dbo.IS_ALIEN('56789')

returns 0

select dbo.IS_ALIEN(56789)

returns 1(我需要return0)

这是我的功能:

ALTER FUNCTION [dbo].[IS_ALIEN] 
    (@alienNAIC CHAR(1))
RETURNS NUMERIC(10,0) 
AS
BEGIN
    DECLARE @nNum NUMERIC(1,0);

    BEGIN
        SET @NnUM = ISNUMERIC(@alienNAIC)
    END
    BEGIN
        IF @nNum = 1 
            RETURN 0;
        END

        RETURN 1;
    END

相同的概念:

select  dbo.IS_ALIEN('AA-11990043')

returns 1

select  dbo.IS_ALIEN(NULL)

returns 1(我需要它return0)

我正在使用 Oracle 函数参考(以下代码只是旧数据库的参考):

create or replace FUNCTION "IS_ALIEN" 
  (  alienNAIC IN char )
  RETURN  NUMBER IS
  nNum number;
BEGIN
    SELECT MOD(alienNAIC, 2) into nNum FROM dual;
    return 0;
EXCEPTION
WHEN INVALID_NUMBER THEN
    return 1;
END;

但是T-SQL函数不允许错误异常。所以我尽量转换得更近一些。

我建议你使用类似这样的东西(我已经将其缩减了一些):

ALTER FUNCTION [dbo].[IS_ALIEN](@alienNAIC NVARCHAR(10))
RETURNS INT -- NOTE: You could also return tinyint or bit
AS
BEGIN
    IF ISNUMERIC(@alienNAIC) = 1 
        RETURN 0;

    RETURN 1;
END

您尝试的问题是存在对 CHAR(1) 的隐式转换,其结果绝对不是@Joel 指出的数字:

SELECT CAST(0 As CHAR(1)) -- returns character '0', ISNUMERIC(0) = 1
SELECT CAST(9 As CHAR(1)) -- returns character '9', ISNUMERIC(0) = 1
SELECT CAST(12345 As CHAR(1)) -- any number over 9 returns character '*', ISNUMERIC(12345) = 0

这是一个我以前从未见过的奇怪的隐式转换案例。通过使参数成为 NVARCHAR(假设未来可能的双字节输入),字符串将被正确检查并且传入的整数将被隐式转换为 NVARCHAR,并且 ISNUMERIC 检查将成功.

编辑 重新阅读问题和评论,您似乎想要识别特定的字符串语法以确定某些内容是否为 "alien" 。如果您愿意 更改业务逻辑以修复明显较差的遗留实现 ,您可以考虑这样的事情:

ALTER FUNCTION [dbo].[temp](@alienNAIC NVARCHAR(10))
RETURNS INT -- NOTE: You could also return tinyint or bit
AS
BEGIN
    IF @alienNAIC like 'AA-%' AND ISNUMERIC(RIGHT(@alienNAIC, LEN(@alienNAIC) - 3)) = 1
        RETURN 1; -- notice this is now 1 instead of 0, we're doing a specific check for 'AA-nnnnn...'

    RETURN 0;
END

请注意,如果要与遗留数据进行交互,应该针对遗留数据对其进行彻底测试——您永远不知道编写不当的遗留系统留下了哪些垃圾数据。解决这个问题很可能会破坏其他东西。如果您确实进行了此更改,请将其记录下来。

如果您只需要检查第一个字符,那么您可以这样做:

CREATE FUNCTION [dbo].[IS_ALIEN] 
    (@alienNAIC VARCHAR(200))
RETURNS TINYINT 
AS
BEGIN
    IF LEFT(@alienNAIC,1) BETWEEN '0' AND '9' RETURN 1;
    RETURN 0
END
GO

您似乎在尝试检查字符串是否以非数字字符开头。可以使用 LIKE 执行此类模式匹配,例如

declare @var nvarchar(10)='A56789'

select 
    case when @var LIKE '[0-9]%' 
         then 0 else 1 
    end AS IsAlien

Returns

1

declare @var nvarchar(10)=56789declare @var int=56789 return 0 因为数字被隐式转换为字符串。

表达式很短,您可能不需要将其转换为函数。如果你这样做,它可以很简单:

create FUNCTION [dbo].[IS_ALIEN]  (@alienNAIC varchar(200))
RETURNS INT 
begin 
    return  case when @alienNAIC LIKE '[0-9]%' 
                             then 0 else 1 
                        end 

end

如果要在 WHERE 子句中执行检查,只需使用 LIKE,而不是任何函数,例如:

WHERE alienNAIC NOT LIKE '[0-9]%'

这个特定的模式只是一个范围搜索,涵盖了 09...... 之间的所有值。服务器可以使用覆盖文本列的索引来快速识别匹配项。当它必须检查函数的 result 时,它不能这样做。它必须在过滤之前计算每一行的值。