SQL Server EncryptByKey(..)函数的@cleartext(2nd)参数的实际数据类型是什么?

时间:2010-02-17 18:48:26

标签: tsql types parameters

我在下面要问的是:此SQL函数的@cleartext参数的实际数据类型是什么? >> ENCRYPTBYKEY(..) - http://msdn.microsoft.com/en-us/library/ms174361.aspx

(如果您在此行下方阅读,则可以按照历史和推理进行操作。我认为它比首次出现时更棘手。)


SQL Server文档声明EncryptByKey(..)函数的 @cleartext(2nd)参数可以接受多种类型:

  

EncryptByKey(@key_GUID, @cleartext [,@ add_authenticator,@ authenticator])

     

@cleartext
是类型的变量    nvarchar,char,varchar,binary,   包含数据的varbinary或nchar   用密钥加密。

^ ^ ^ ^ ^ ^ ^ ^ ^ - - - - - 但它的实际声明数据类型是什么? ...

如果我要创建一个自定义函数(完全独立于上面给出的EncryptByKey示例)我给出了一个自定义参数的实际数据类型,以便它以相同的方式接受所有相同的类型?

编辑1:我实际上是在自定义中包装SQL EncryptByKey函数  UDF功能,我想重新创建相同的功能  要传递给的参数类型  它。这就是我想要按类型创建完全相同的参数的原因。

修改2 :如果我尝试使用sql_variant,则会导致错误

  

Msg 8116,Level 16,State 1,Procedure   EncryptWrapper,第17行参数数据   类型sql_variant对于无效   EncryptByKey函数的参数2。

编辑3:

这是我的自定义包装函数 - 以及直接问题。 @cleartext的数据类型应该直接传递给EncryptByKey?

ALTER FUNCTION [dbo].[EncryptWrapper]
(
 @key_GUID uniqueidentifier,
 @cleartext -- ???????????  <<< WHAT TYPE ????????????????
 @add_authenticator int = 0,
 @authenticator sysname = NULL
)
RETURNS varbinary(8000)
AS
BEGIN

    -- //Calling a SQL Server builtin function. 
    -- //Second param @cleartext is the problem. What data type should it be?
 Return EncryptByKey(@key_GUID, @cleartext, @add_authenticator, @authenticator)

END

注意:我不应该使用CAST或CONVERT - 我只需要为@cleartext param使用正确的数据类型。

编辑4 :发现EncryptByKey(..)@cleartext参数不是以下类型

  • sql_variant - 传递时出现错误
  • varbinary - 限制性太强 - 不允许传递EncryptByKey(..)否则接受的文本类型
  • sysnamenvarcharvarchar - 奇怪的行为 - 往往只接受参数文字的第一个字符或其他内容

2 个答案:

答案 0 :(得分:2)

尝试sql_variant:

CREATE FUNCTION [dbo].[yourFunction]
(
     @InputStr      sql_variant   --can not be varchar(max) or nvarchar(max)
)
returns
varchar(8000)

BEGIN
    --can use SQL_VARIANT_PROPERTY(@InputStr,'BaseType') to determine given datatype

    --do whatever you want with @inputStr here
    RETURN CONVERT(varchar(8000),@InputStr)  --key is to convert the sql_varient to something you can use

END
GO

关键是将sql_varient转换为可以在函数中使用的东西。您可以使用IF语句并检查BaseType并将sql_varient转换回本机数据类型

修改
这是一个如何获取原始数据类型的示例:

CREATE FUNCTION [dbo].[yourFunction]
(
     @InputStr      sql_variant   --can not be varchar(max) or nvarchar(max)
)
returns
varchar(8000)

BEGIN
    DECLARE @Value varchar(50)
    --can use SQL_VARIANT_PROPERTY(@InputStr,'BaseType') to determine given datatype

    --do whatever you want with @inputStr here
    IF @InputStr IS NULL
    BEGIN
        SET @value= 'was null'
    END
    ELSE IF SQL_VARIANT_PROPERTY(@InputStr,'BaseType')='char'
    BEGIN
        --your special code here
        SET @value= 'char('+CONVERT(varchar(10),SQL_VARIANT_PROPERTY(@InputStr,'MaxLength '))+') - '+CONVERT(varchar(8000),@InputStr)
    END
    ELSE IF SQL_VARIANT_PROPERTY(@InputStr,'BaseType')='datetime'
    BEGIN
        --your special code here
        SET @value= 'datetime - '+CONVERT(char(23),@InputStr,121)
    END
    ELSE IF SQL_VARIANT_PROPERTY(@InputStr,'BaseType')='nvarchar'
    BEGIN
        --your special code here
        SET @value= 'nvarchar('+CONVERT(varchar(10),CONVERT(int,SQL_VARIANT_PROPERTY(@InputStr,'MaxLength '))/2)+') - '+CONVERT(varchar(8000),@InputStr)
    END
    ELSE
    BEGIN
        --your special code here
        set @value= 'unknown!'
    END

    RETURN  @value

END
GO

测试出来:

DECLARE @x char(5), @z int, @d datetime, @n nvarchar(27)
SELECT @x='abc',@d=GETDATE(),@n='wow!'
select [dbo].[yourFunction](@x)
select [dbo].[yourFunction](@d)
select [dbo].[yourFunction](@z)
select [dbo].[yourFunction](@n)

测试输出:

-------------------------------------
char(5) - abc  

(1 row(s) affected)


-------------------------------------
datetime - 2010-02-17 15:10:44.017

(1 row(s) affected)


-------------------------------------
was null

(1 row(s) affected)


-------------------------------------
nvarchar(27) - wow!

(1 row(s) affected)

答案 1 :(得分:0)

ENCRYPTBYKEY()几乎肯定不是用vanilla T-SQL编写的。它不需要遵循T-SQL数据类型规则。

也就是说,如果你想为它编写一个包装器,请使用SQL_VARIANT作为@cleartext参数,就像KM建议的那样。

如果ENCRYPTBYKEY()对@cleartext的最大长度不敏感,则可以将所有CHAR / VARCHAR复制到VARCHAR(8000),将所有NCHAR / NVARCHAR复制到NVACHAR(4000)。

否则你可能是SOL:任何尊重最大长度的数据类型转换 - 例如,CHAR(10)vs CHAR(20) - 都需要动态SQL,所以你必须把它写成一个存储过程,而不是而不是一个功能。那时,它不再是一个包装器了。