在CASE WHEN / IIF中使用时,SQL HASHBYTES函数返回奇怪的输出

时间:2018-05-08 18:45:09

标签: sql sql-server stored-procedures hashbytes

我编写了一个存储过程,用于散列某列的值。我需要在CASE WHEN或IIF语句中使用此HASHBYTES函数,如下所示:

DECLARE @Hash varchar(255) = 'testvalue'
SELECT    IIF(1=1, HASHBYTES('SHA1',@Hash), @Hash)
SELECT CASE WHEN 1=1 THEN HASHBYTES('SHA1',@Hash) END  AS Hashcolumn

我无法理解为什么我从上述查询中获得不同的输出?似乎每当我在CASE WHEN / IIF语句中添加ELSE时,它都会返回一串奇怪的字符(如上例中的ü<þ+OUL'RDOk{­\Ìø)。

谁能告诉我为什么会这样?我需要使用CASE WHEN或IIF。

谢谢你们

2 个答案:

答案 0 :(得分:5)

IIF从true_value和false_value中的类型返回带有highest precedence的数据类型。在这种情况下,@Hash1varchar(255),因此您的结果会被转换为varchar(255)。见下文。

DECLARE @Hash varchar(255) = 'testvalue'
SELECT cast(HASHBYTES('SHA1',@Hash) as varchar(255))

同样,CASE的工作方式相同。但是,如果您没有添加与数据类型冲突的ELSE或其他WHEN,它将起作用。这是因为暗示了ELSE NULL。即。

SELECT CASE WHEN 1=1 THEN HASHBYTES('SHA1',@Hash) END

但是,如果您添加另一个检查,则优先级将启动,并且将进行转换。

SELECT CASE WHEN 1=1 THEN HASHBYTES('SHA1',@Hash) WHEN 1=2 THEN @Hash END AS Hashcolumn 
SELECT CASE WHEN 1=1 THEN HASHBYTES('SHA1',@Hash) ELSE @Hash END AS Hashcolumn 

答案 1 :(得分:2)

选择查询的输出是虚拟表。在关系数据库中,表的一列被约束为单个数据类型..所以这里发生的是隐式转换是由服务器引擎完成的,以便呈现一个sigle类型,因此返回奇怪的字符。

转换的本质是@scsimon说它遵循最高优先顺序。

以下查询应该有所帮助。

DECLARE @Hash varchar(255) = 'testvalue'
SELECT    IIF(1=1, CONVERT(VARCHAR(255),HASHBYTES('SHA1',@Hash),2), @Hash)
SELECT CASE WHEN 1=2 THEN CONVERT(VARCHAR(255),HASHBYTES('SHA1',@Hash),2) 
      ELSE @Hash END  AS Hashcolumn