在没有引号 T-SQL / SQL Server 2012 的函数中传递值?
Posted
技术标签:
【中文标题】在没有引号 T-SQL / SQL Server 2012 的函数中传递值?【英文标题】:Passing value in a function without quote T-SQL / SQL Server 2012? 【发布时间】:2017-09-25 21:33:52 【问题描述】:我需要帮助我在 SQL Server 2012 中创建用于检查输入值的函数。如果函数检测到数字 - 返回 0,如果检测到字符返回 1。
但是对于相同的数字,我得到了 2 个不同的结果,无论是带引号还是不带引号。
select dbo.IS_ALIEN('56789')
返回 0
select dbo.IS_ALIEN(56789)
返回 1(我需要返回 0)
这是我的功能:
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')
返回 1
或
select dbo.IS_ALIEN(NULL)
返回 1(我需要它返回 0)
我正在使用 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 函数不允许出错异常。所以我尝试转换更接近。
【问题讨论】:
提示:在 management studio 中运行SELECT CAST(56789 As CHAR(1))
并检查结果。这是 Sql Server 在您的任何代码运行之前就将其转换为您的参数类型的问题。听起来您需要使用 sql_variant
类型解决问题,这并不容易。
啊,我得到一个星号 (*)
始终使用标签指定服务器的版本。如果您使用的是 2008 及更高版本,则可以使用 ISNUMERIC 函数。顺便说一句,当您将@alienNAIC char(1) 定义为参数时,它只需要输入的第一个字符。
感谢我修改了标题,它是 sql server 2012。是的,我正在尝试检查是否为空、数字或字母。该字段将收到 Null 或 Number 或 AA。所以如果是 AA,它是一个外星人,所以返回 1。如果是数字或 null,则表示不是外星人,返回 0。但我没有像在 Oracle 中那样得到这些结果。
看起来您使用的是 Oracle,但您使用 tsql 进行了标记。顺便说一句,如果目的是检查外星人,您只需要检查前 2 个字母并确保它们是“AA”。然后删除“AA-”并确保剩余部分是数字。我不确定为什么你有这种方法来实现这一点。请修复标签。
【参考方案1】:
我建议你使用这样的东西(我已经把它剪掉了一些):
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
检查将成功。
编辑 重新阅读问题和 cmets,您似乎想要识别特定的字符串语法以确定某物是否是“外星人”。如果您愿意更改业务逻辑以解决显然是糟糕的遗留实现,您可以考虑这样的事情:
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
请注意,如果要与旧数据交互,则应针对旧数据进行彻底测试 - 您永远不知道编写不佳的旧系统留下了哪些垃圾数据。解决这个问题很可能会破坏其他事情。如果您确实进行了此更改,请做好记录。
【讨论】:
感谢您对本次修复所做的更改。这就是我要找的。span> 【参考方案2】:如果您只需要检查第一个字符,那么您可以这样做:
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
【讨论】:
【参考方案3】:您似乎正在尝试检查字符串是否以非数字字符开头。可以使用LIKE 执行此类模式匹配,例如
declare @var nvarchar(10)='A56789'
select
case when @var LIKE '[0-9]%'
then 0 else 1
end AS IsAlien
返回
1
declare @var nvarchar(10)=56789
和 declare @var int=56789
都返回 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]%'
这个特定的模式只是一个范围搜索,涵盖了0
和9......
之间的所有值。服务器可以使用覆盖文本列的索引来快速识别匹配项。当它必须检查函数的 result 时,它不能这样做。它必须在过滤之前计算每一行的值。
【讨论】:
以上是关于在没有引号 T-SQL / SQL Server 2012 的函数中传递值?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 T-SQL 中的 XML 字符串中的属性中转义双引号?
SQL Server 2005 T-SQL中的Base64编码
使用 SSIS OR T-SQL 将一列带引号和不带引号的逗号分隔值拆分为多列
SQL Server (T-SQL) BAIv2 银行文件导入噩梦