我正在处理一个表,其中一堆任意设置存储为VARCHAR(255)
值。我负责处理的特定代码是需要递增并返回给调用者的序列号。 (再次注意,序列“number”存储为VARCHAR
,这是我无法控制的。)
因为它是一个序列号,我真的不想在单独的步骤中选择和更新。当我过去用实际的数字字段处理过这种事情时,我的方法就像是
UPDATE TABLE SET @SEQ_NUM = VALUE = VALUE + 1
增加值并在一个swell foop中给我更新的值。我想在这种情况下,我会尝试与演员一样的基本事情:
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,Level 16,State 1,Line 4 The collation 接收变量的'SQL_Latin1_General_CP1_CI_AS'不等于 列'VALUE'的排序规则'Latin1_General_BIN'。
我理解这意味着什么,但我不明白为什么会发生这种情况,或者通过扩展,如何解决这个问题。
除了修复特定错误之外,我欢迎提出增加char序列“数字”的替代方法的建议。
答案 0 :(得分:1)
从其中一条评论中,您可能已经听过这样的声音,但这是我的建议:
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
答案 1 :(得分:0)
手动维护序列号绝不是我想要使用的解决方案,但我可以理解可能存在约束。
如果将其细分为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
答案 2 :(得分:0)
您可以继续在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
这种简单的重写可以防止db-engine抱怨@Variable
和Column
之间的数据类型差异(例如VARCHAR
与NVARCHAR
),并且看起来更像是“便携式”的方式进行古怪的更新(如果有的话)