作为生成零填充唯一标识符的请求的一部分,我创建了我认为简单的语句
right('00000000' + convert(char(6),ID),6)
但是,这根本不是零填充字符。 进一步的调查显示,一切都不像我预期的那样。 参见:
drop table #test
go
select --top 30
right('00000000' + convert(varchar(6),ID),6) varcharPadRight, --results in varchar(6) in tempdb
right('00000000' + convert(char(6),ID),6) charPadRight, --results in varchar(6) in tempdb
right('00000000' + convert(char(6),ID),20) charPadRight20, --results in varchar(14) in tempdb
right('00000000' + convert(varchar(6),ID),20) vcharPadRight20 --results in varchar(14) in tempdb
into #test
from requestidentifier aTableWithAnIntIdentityColumn
where aTableWithAnIntIdentityColumn.ID in (1,100,1000)
go
select * from #test
select left(so.name, 5) name,sc.name, sc.xtype, sc.length from tempdb..sysobjects so inner join tempdb..syscolumns sc on so.id = sc.id where so.name like '%test%'
结果如下:
varcharPadRight charPadRight charPadRight20 vcharPadRight20
--------------- ------------ -------------- ---------------
000100 100 00000000100 00000000100
001000 1000 000000001000 000000001000
000001 1 000000001 000000001
和
tableName colName xtype length
--------- -------------- ----- ------
#test varcharPadRigh 167 6
#test charPadRight 167 6
#test charPadRight20 167 14
#test vcharPadRight2 167 14
其中xtype为167是varchar。
有没有人可以解释导致这些(对我而言)意外结果的操作顺序?
(此行为在SQL Server 2005和2008中是一致的)
答案 0 :(得分:2)
简单的解释是char数据类型在右边有空格,使其成为变量的长度。因此,如果你有一个char(6)并将其设置为'3',那么变量中的值实际上将是3空间空间空间空间。这是一个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不会在末尾填充空格,因此它的工作方式与您期望的完全相同。
PROOF:
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)
答案 1 :(得分:1)
将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。
right('00000000' + rtrim(convert(char(6),ID)),6)