使变量的数据类型匹配列的数据类型

时间:2018-01-04 14:54:31

标签: sql-server

本地变量的数据类型需要与现有表列的数据类型匹配。

在过去,我会查找列的数据类型并手动匹配,如下所示:

-- schema follows...
CREATE TABLE [dbo].[TestTable]
(
    [Id] BIGINT NOT NULL PRIMARY KEY, 
    [valueholder] NVARCHAR(MAX) NULL
)

...
-- manually set data type to match above
DECLARE @tempvalueholder AS NVARCHAR(MAX)

问题是,如果架构在线路的某处发生变化,我必须手动查找和更新。

假设列名和表名保持不变,是否有办法将局部变量的数据类型与列的数据类型联系起来?

我知道如何以类似的方式获取数据类型,但无法弄清楚如何连接变量声明:

SELECT DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='testtable'
AND COLUMN_NAME='valueholder'

3 个答案:

答案 0 :(得分:0)

与Oracle不同,sql-server不支持 您唯一能做的就是当表的模式发生变化时,找到所有过程,触发器,访问该表的函数以及检查/更正声明。

这是一个小查询,可帮助您查找使用该表的所有过程,函数和触发器:

SELECT DISTINCT
       o.name AS Object_Name,
       o.type_desc,
       m.*
FROM   sys.sql_modules m
  INNER JOIN sys.objects o ON m.object_id = o.object_id
WHERE m.definition Like '%MyTableName%';

答案 1 :(得分:0)

我可以建议使用一个临时表,它与原始表的结构完全相同。

因此,即使更改了表列的数据类型,也不会影响存储过程代码。

但它也为开发人员编码过载

这是一个示例

create procedure TestTable10_readbyId (@Id bigint)
as
begin

DECLARE @tempvalueholder AS NVARCHAR(MAX)

select * into #t from TestTable10 where 1 = 0
insert into #t (Id) values (@Id)

update #t
set valueholder = TestTable10.valueholder
from #t
inner join TestTable10 on TestTable10.Id = #t.Id 
and TestTable10.Id = @Id

select @tempvalueholder = valueholder
from TestTable10
where Id = @Id

select @tempvalueholder as valueholder
select valueholder from #t
end

你看我已经保留了两种方法

一个是使用数据变量声明 其他是创建一个临时表,它为选择列表中的每一列逻辑生成一个变量

当然,对于第二种解决方案,我们需要一个具有NULL值的行。

我实际上不喜欢这种方法,因为你必须在编码期间考虑所有这些。所以我插入了一个带有空值的虚拟行,但只插入了我认为在下面的代码块中有用的PK字段

不是通过先设置其值来返回变量,而是更新临时表列,然后在此示例中返回此行列。

答案 2 :(得分:0)

你需要创建" DECLARE @VariableName DATATYPE"动态。这意味着变量和其余代码应该在动态SQL的范围内。如果这符合您的需求,您可以尝试:

DECLARE
    @DataType1 VARCHAR(16)
    , @DataType2 VARCHAR(16)
    , @DynamicSQL NVARCHAR(MAX) = N'';

SELECT
    @DataType1 = UPPER(DATA_TYPE)
    , @DataType2 = 
        CASE
            WHEN (DATA_TYPE IN ('char', 'nchar')) THEN CONCAT(UPPER(DATA_TYPE), '(', CHARACTER_MAXIMUM_LENGTH, ')')
            WHEN (DATA_TYPE IN ('varchar', 'nvarchar')) THEN CASE WHEN (CHARACTER_MAXIMUM_LENGTH = -1) THEN CONCAT(UPPER(DATA_TYPE), '(MAX)') ELSE CONCAT(UPPER(DATA_TYPE), '(', CHARACTER_MAXIMUM_LENGTH, ')') END
            WHEN (DATA_TYPE IN ('decimal', 'numeric')) THEN CONCAT(UPPER(DATA_TYPE), '(', NUMERIC_PRECISION, ', ', NUMERIC_SCALE, ')')
            WHEN (DATA_TYPE = 'float') THEN CASE WHEN (NUMERIC_PRECISION = 53) THEN UPPER(DATA_TYPE) ELSE CONCAT(UPPER(DATA_TYPE), '(', NUMERIC_PRECISION, ')') END
            WHEN (DATA_TYPE = 'real') THEN CASE WHEN (NUMERIC_PRECISION = 24) THEN UPPER(DATA_TYPE) ELSE CONCAT(UPPER(DATA_TYPE), '(', NUMERIC_PRECISION, ')') END
            WHEN (DATA_TYPE = 'image') THEN NULL
            WHEN (DATA_TYPE = 'time') THEN CASE WHEN (DATETIME_PRECISION = 7) THEN UPPER(DATA_TYPE) ELSE CONCAT(UPPER(DATA_TYPE), '(', DATETIME_PRECISION, ')') END
            WHEN (DATA_TYPE = 'varbinary') THEN CASE WHEN (CHARACTER_MAXIMUM_LENGTH = -1) THEN CONCAT(UPPER(DATA_TYPE), '(MAX)') ELSE CONCAT(UPPER(DATA_TYPE), '(', CHARACTER_MAXIMUM_LENGTH, ')') END
            ELSE UPPER(DATA_TYPE)
        END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
    TABLE_SCHEMA = 'SchemaName'
    AND TABLE_NAME = 'TableName'
    AND COLUMN_NAME = 'ColumnName';

IF(@DataType2 IS NULL)
    BEGIN RAISERROR (N'Data type %s is invalid for local variables.', 16, 1, @DataType1); END
ELSE
    BEGIN
        SET @DynamicSQL += N'
DECLARE @VariableName ' + @DataType2 + ';'

        SET @DynamicSQL += N'
SET @VariableName = 15;

SELECT @VariableName AS [@VariableName];
';

        EXEC (@DynamicSQL);
    END
相关问题