将sql_variant转换为以varchar提供的data_type

时间:2015-06-02 08:30:21

标签: sql sql-server stored-procedures casting

我有一个以下的sql表:

 Types table

    --------------------------------------
    |Name(varchar(50))|Type (varchar(50))|
    --------------------------------------
    | Car             | varchar(50)      |
    | Apples          | int              |
    --------------------------------------

我正在使用另一个表来存储值,例如:

Apples table:

    ----------------------------
    |Value (providedType - int)|
    ----------------------------
    |50                        |
    |60                        |
    ----------------------------

要在这些表中插入值,我使用的是存储过程(部分):

CREATE PROCEDURE [dbo].[AddValue]
@value sql_variant
@name varchar(50)
@tableName (50)
AS
BEGIN

DECLARE @Sql NVARCHAR(MAX)
DECLARE @valueType VARCHAR(50)
SET @valueType = (SELECT [Type] FROM [dbo].[Types] WHERE [Name] = @name)

SET @Sql = N'INSERT INTO [dbo].'+ @tableName + N' VALUES(' + @value + N')'
EXECUTE sp_executesql @Sql 
...

动态执行将抛出异常,即不允许隐式转换sql_variant。有没有办法将sql_variant类型转换为varchar提供的类型? 如:

CONVERT(@valueType, @value)

其中@valueType是varchar而不是datetype

2 个答案:

答案 0 :(得分:2)

是的,您可以将sql_variants作为参数传递给sp_executesql,但是您需要使用" Cast to"继续使用动态SQL路由。输入,并使用您为CAST中使用的列确定的类型名称。

以此为例:

CREATE TABLE Foo
(
    ID INT
);
declare @type NVARCHAR(20) = N'INT'; -- Substitute your Type here.
declare @tableName NVARCHAR(50) = 'Foo';
declare @value sql_variant;
set @value = 1234;
DECLARE @Sql AS NVARCHAR(MAX) = N'INSERT INTO [dbo].'+ @tableName +
           N' VALUES(CAST(@value AS ' + @type + '))';
EXECUTE sp_executesql @Sql, N'@value sql_variant', @value = @value;  

毋庸置疑,您需要确保您的@tableNameType数据需要针对白名单运行,以防止动态Sql的Sql Injection漏洞此

SqlFiddle here

答案 1 :(得分:0)

/*Convert varchar to sql_variant*/

--variable / variaveis

DECLARE @in varchar(max) = 'hello world'
       ,@out sql_variant
       
--query
declare @query nvarchar(max) = 'SELECT @in = '+char(39)+@in+char(39)
                                                                
EXEC sp_executesql @query, 
                   -- declare OUT(s)
                   N'@in sql_variant OUTPUT'

                   ---transfer / tranferir
                   ,@in    = @out OUTPUT 
                   
--show / exibir
SELECT @out