我正在处理一个表,其中一堆任意设置都存储为VARCHAR(255)
值。我要处理的特定序列号需要增加并返回给调用方。 (同样,请注意,序列“数字”存储为VARCHAR
,这是我无法控制的)。
因为这是一个序列号,所以我真的不想在单独的步骤中进行选择和更新。当我过去用实际的数字字段处理这类事情时,我的方法一直是
UPDATE TABLE SET @SEQ_NUM = VALUE = VALUE + 1
这将增加值,并在一浪涌现的情况下为我提供更新的值。我认为在这种情况下,我会尝试使用演员表进行相同的基本操作:
DECLARE @SEQ_NUM VARCHAR(255)
UPDATE SOME_TABLE
SET @SEQ_NUM = VALUE = CAST((CAST(VALUE AS INT) + 1) AS VARCHAR)
WHERE NAME = 'SOME_NAME'
只要我不尝试将结果分配给变量,实际的更新就可以正常工作;我一收到,就会收到以下错误:
Msg 549,第16级,状态1,第4行,整理接收变量的“ SQL_Latin1_General_CP1_CI_AS”不等于列“ VALUE”的排序规则“ Latin1_General_BIN”。
我理解这意味着什么,但我不明白为什么会发生这种情况,或者不知道如何解决此问题。
除了解决特定错误外,我欢迎提出其他增加char序列“数字”的方法的建议。
从其中一条评论中,听起来您可能已经对此赞叹不已,但是我建议您这样做:
UPDATE TABLE
SET VALUE = CAST((CAST(VALUE AS INT) + 1) AS VARCHAR)
OUTPUT inserted.VALUE
WHERE NAME = 'SOME_NAME'
这将像SELECT
语句一样输出新值。如果要在SQL中执行此操作,也可以将inserted.VALUE
强制转换为int
。
如果要将该值放入@SEQ_NUM
中而不是从语句/存储过程中输出该值,则不能使用标量变量,但是可以将其抽入表变量中,如下所示:
DECLARE @SEQ_NUM AS TABLE ( VALUE VARCHAR(255) );
UPDATE TABLE
SET VALUE = CAST((CAST(VALUE AS INT) + 1) AS VARCHAR)
OUTPUT inserted.VALUE INTO @SEQ_NUM ( VALUE )
WHERE NAME = 'SOME_NAME'
SELECT VALUE FROM @SEQ_NUM
手动维护序列号绝不是我想使用的解决方案,但我可以理解,对此可能存在一些限制。
如果将其分解为2个步骤,则可以解决此问题。注意,为了使此示例代码正常工作,我替换了WHERE
子句:
CREATE TABLE #SOME_TABLE ( [VALUE] VARCHAR(255) )
INSERT INTO #SOME_TABLE
( VALUE )
VALUES ( '12345' )
DECLARE @SEQ_NUM VARCHAR(255)
UPDATE #SOME_TABLE
SET [VALUE] = CAST(( CAST([VALUE] AS INT) + 1 ) AS VARCHAR(255))
WHERE 1 = 1
SELECT *
FROM #SOME_TABLE
SELECT @SEQ_NUM = [VALUE]
FROM #SOME_TABLE
WHERE 1 = 1
SELECT @SEQ_NUM
DROP TABLE #SOME_TABLE
[您可以继续在OP中使用古怪的更新,但是您必须像这样将@Variable = Column = Expression
语句中的三重分配UPDATE
拆分为@Variable = Expression
和Column = @Variable
的两个简单分配
CREATE TABLE #SOME_TABLE (
NAME VARCHAR(255)
, VALUE VARCHAR(255) COLLATE Latin1_General_BIN
)
INSERT #SOME_TABLE SELECT 'SOME_NAME', '42'
DECLARE @SEQ_NUM VARCHAR(255)
/*
-- this quirky update fails on COLLATION mismatch or data-type mismatch
UPDATE #SOME_TABLE
SET @SEQ_NUM = VALUE = CAST((CAST(VALUE AS INT) + 1) AS VARCHAR)
WHERE NAME = 'SOME_NAME'
*/
-- this quirky update works in all cases
UPDATE #SOME_TABLE
SET @SEQ_NUM = CAST((CAST(VALUE AS INT) + 1) AS VARCHAR)
, VALUE = @SEQ_NUM
WHERE NAME = 'SOME_NAME'
SELECT *, @SEQ_NUM FROM #SOME_TABLE
此简单的重写可以防止数据库引擎也抱怨@Variable
和Column
之间的数据类型不同(例如VARCHAR
与NVARCHAR
),并且看起来像是一种更“方便”的方式来进行古怪的更新(如果有这样的东西)