Sql server SQL Server pad right脚本中无法解释的运算符优先级
作为生成零填充唯一标识符请求的一部分,我创建了一个我认为简单的语句Sql server SQL Server pad right脚本中无法解释的运算符优先级,sql-server,sql-server-2005,tsql,sql-server-2008,Sql Server,Sql Server 2005,Tsql,Sql Server 2008,作为生成零填充唯一标识符请求的一部分,我创建了一个我认为简单的语句 right('00000000' + convert(char(6),ID),6) 然而,这根本不是零填充字符。 进一步的调查显示,这一切并不像我预期的那样。 见: 其结果是: varcharPadRight charPadRight charPadRight20 vcharPadRight20 --------------- ------------ -------------- --------------- 000100
right('00000000' + convert(char(6),ID),6)
然而,这根本不是零填充字符。
进一步的调查显示,这一切并不像我预期的那样。
见:
其结果是:
varcharPadRight charPadRight charPadRight20 vcharPadRight20
--------------- ------------ -------------- ---------------
000100 100 00000000100 00000000100
001000 1000 000000001000 000000001000
000001 1 000000001 000000001
及
其中,xtype 167是一个varchar
有没有人能解释导致这些(对我来说)意外结果的操作顺序
(这种行为在SQL Server 2005和2008中是一致的)将int转换为char(6)是左对齐的,因此
int -> char(6) -> '000' + char(6) -> right('000' + char(6))
1 -> 1______ -> '0001_____' -> '1_____'
10 -> 10_____ -> '00010____' -> '10____'
etc
因此,代码中的rtrim将给出预期的结果
e、 g
简单的解释是char数据类型的右边有空格,使其成为变量的长度。因此,如果您有一个char(6)并将其设置为“3”,那么变量中的值实际上是3-space-space-space-space-space。这是一个3,后跟5个空格,使总长度=6个字符 在字符串左侧添加6个零时,SQL正在进行一些数据类型转换。硬编码字符串将导致varchar,因此“000000”的数据类型为varchar(6)。当您附加一个char和一个varchar时,结果是一个长度组合在一起的varchar
'000000' + Convert(Char(6), int)
VarChar(6) + Char(6)
varchar(12)
Char(6)部分仍将在数据右侧填充空格,因此当您使用最右边的6个字符时,您将获得空格
varchar的末尾没有空格,因此它的工作方式与您预期的完全相同
证明:
Declare @ID Int
Set @Id = 3
-- Data type after converting to char (results in char(6))
SELECT SQL_VARIANT_PROPERTY(Convert(Char(6), @id), 'BaseType') As DatType,
SQL_VARIANT_PROPERTY(Convert(Char(6), @id), 'MaxLength') As Length,
Convert(Char(6), @id)
-- data type of hard coded string (Results in varchar(6))
SELECT SQL_VARIANT_PROPERTY('000000', 'BaseType') As DatType,
SQL_VARIANT_PROPERTY('000000', 'MaxLength') As Length,
'000000'
-- data type of varchar concatenate char (Results in varchar(12))
SELECT SQL_VARIANT_PROPERTY('000000' + Convert(Char(6), @id), 'BaseType') As DataType,
SQL_VARIANT_PROPERTY('000000' + Convert(Char(6), @id), 'MaxLength') As Length,
'000000' + Convert(Char(6), @id)
-- data type of the result (results in varchar(6))
SELECT SQL_VARIANT_PROPERTY(Right('000000' + Convert(Char(6), @id), 6), 'BaseType') As DataType,
SQL_VARIANT_PROPERTY(Right('000000' + Convert(Char(6), @id), 6), 'MaxLength') As Length,
Right('000000' + Convert(Char(6), @id), 6)
只是使用
varchar()
而不是char()
似乎是目前为止最明智的做法-它避免了在第一个位置添加填充字符。@Andriy M-可能,但我很困惑,因为OP似乎意识到varchar()
是有效的(根据他们的第一个示例),所以我想我可能遗漏了什么。是的,我知道varchar正在修复它,只是想知道为什么。为SQL_VARIANT_属性干杯,这比tempdb hacking要好得多。
right('00000000' + rtrim(convert(char(6),ID)),6)
'000000' + Convert(Char(6), int)
VarChar(6) + Char(6)
varchar(12)
Declare @ID Int
Set @Id = 3
-- Data type after converting to char (results in char(6))
SELECT SQL_VARIANT_PROPERTY(Convert(Char(6), @id), 'BaseType') As DatType,
SQL_VARIANT_PROPERTY(Convert(Char(6), @id), 'MaxLength') As Length,
Convert(Char(6), @id)
-- data type of hard coded string (Results in varchar(6))
SELECT SQL_VARIANT_PROPERTY('000000', 'BaseType') As DatType,
SQL_VARIANT_PROPERTY('000000', 'MaxLength') As Length,
'000000'
-- data type of varchar concatenate char (Results in varchar(12))
SELECT SQL_VARIANT_PROPERTY('000000' + Convert(Char(6), @id), 'BaseType') As DataType,
SQL_VARIANT_PROPERTY('000000' + Convert(Char(6), @id), 'MaxLength') As Length,
'000000' + Convert(Char(6), @id)
-- data type of the result (results in varchar(6))
SELECT SQL_VARIANT_PROPERTY(Right('000000' + Convert(Char(6), @id), 6), 'BaseType') As DataType,
SQL_VARIANT_PROPERTY(Right('000000' + Convert(Char(6), @id), 6), 'MaxLength') As Length,
Right('000000' + Convert(Char(6), @id), 6)