SQL代码:
ALTER PROCEDURE [dbo].[psGetReprintNLot]
@codOrder VARCHAR(15)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT
codPackedBatch AS codPackedBatch
FROM
PackedOrder
INNER JOIN
[Order] ON PackedOrder.codOrder = [Order].codOrder
WHERE
(PackedOrder.codOrder = @codOrder OR @codOrder IS NULL)
AND RIGHT([PackedOrder].codPackedBatch, 1) <> 8
ORDER BY
codPackedBatch ASC
IF @@Error <> 0
RETURN -1
ELSE
RETURN 0
SET NOCOUNT OFF
END
问题:
我有一个{= {1}},字符串='M18111301'。
@codOrder
当我尝试执行存储过程时,出现此错误:
消息245,级别16,状态1,过程psGetReprintNLot,第47行
将varchar值'M18111301'转换为数据类型int时,转换失败。
但是当我尝试执行时:
Exec [psGetReprintNLot] 'M18111301'
它按预期工作。如果我输入字符串,如何获取值?
如果我尝试以下操作:我得到的是'M'的正确结果,而不是正常的'72 ... 46'
Exec [psGetReprintNLot] '721718346'
答案 0 :(得分:1)
出现问题是因为您的PackedOrder.codOrder
列具有INT数据类型,并且您正在将其与varchar进行比较:
PackedOrder.codOrder = @codOrder
当字符串@codOrder仅包含数字时,SQLServer将成功将@codOrder的内容转换为INT,然后运行查询
当您的@codOrder也包含字母字符时,SQLServer将无法将其转换为int并给出此错误
SQLServer不会尝试将所有表数据转换为varchar来执行string:string比较,因为隐式转换表数据以匹配这样的变量会浪费资源,并且在大多数情况下,数据转换意味着索引不能用过的。所有这些都意味着转换数百万行以匹配一个变量的数据类型会严重影响性能,因此不应该这样做
如果您确实想显式地进行此转换,则可以将表列CAST()转换为varchar,但由于表列是INT,因此请参见inf,它将永远不会包含M18111301
,因此将一百万个INT转换为varchar,然后在其中搜索字母数字是100%毫无意义的练习。
最好改变一下过程,以使用INT类型的@codOrder代替,并停止尝试向其中输入字母数字数据
或者,根据问题下的注释,如果M18111301
在某种程度上与表中的数据有关(例如,表中确实包含18111301
,则应将M切掉),然后修改变量,使其与表中的内容匹配,然后进行搜索
为响应您的修改,并在下面发表我的评论:
ALTER PROCEDURE [dbo].[psGetReprintNLot]
@codOrder VARCHAR(15)
AS
BEGIN
SET NOCOUNT ON;
IF @codOrder LIKE 'M%'
SELECT DISTINCT codPackedBatch AS codPackedBatch
FROM PackedOrder
WHERE (PackedOrder.codPackedOrder = @codOrder OR @codOrder IS NULL)
AND RIGHT([PackedOrder].codPackedBatch, 1) <> 8
ORDER BY codPackedBatch ASC
ELSE
SELECT DISTINCT codPackedBatch as codPackedBatch
FROM PackedOrder
INNER JOIN [Order] ON PackedOrder.codOrder = [Order].codOrder
WHERE (PackedOrder.codOrder = @codOrder or @codOrder IS NULL)
AND Right([PackedOrder].codPackedBatch,1) <> 8 order by codPackedBatch Asc
END IF;
IF @@Error <> 0
RETURN -1;
ELSE
RETURN 0;
SET NOCOUNT OFF;
END
?
如果您期望@codOrder值在其他任何地方都具有任何字母字符,例如123TP456
,则可以使用LIKE '%[A-Z]%'
答案 1 :(得分:0)
可能您正在寻找
ALTER PROCEDURE [dbo].[psGetReprintNLot]
@codOrder VARCHAR(15)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT codPackedBatch as codPackedBatch
FROM PackedOrder
INNER JOIN [Order] ON PackedOrder.codOrder = [Order].codOrder
WHERE (@codOrder IS NULL or @codOrder = case when isnumeric(@codOrder) then PackedOrder.codOrder else PackedOrder.codPackedOrder end)
AND Right([PackedOrder].codPackedBatch,1) <> 8 order by codPackedBatch Asc
IF @@Error <> 0
RETURN -1
ELSE
RETURN 0
SET NOCOUNT OFF
END