SQL-“增加”一个char值会导致排序规则错误

问题描述 投票:2回答:3

我正在处理一个表,其中一堆任意设置都存储为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序列“数字”的方法的建议。

sql sql-server sql-server-2008 collation
3个回答
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

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

0
投票

[您可以继续在OP中使用古怪的更新,但是您必须像这样将@Variable = Column = Expression语句中的三重分配UPDATE拆分为@Variable = ExpressionColumn = @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

此简单的重写可以防止数据库引擎也抱怨@VariableColumn之间的数据类型不同(例如VARCHARNVARCHAR),并且看起来像是一种更“方便”的方式来进行古怪的更新(如果有这样的东西)

© www.soinside.com 2019 - 2024. All rights reserved.