2

T-SQLで変数型のデータ型をキャストすることは可能ですか?

つまり、文字列リテラルを想定しているため、これは機能しませんが、要点はわかります。

select @DataType = Data_Type
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'emp'
and COLUMN_NAME = 'emp_id'

SELECT
cast(emp_id as @DataType)
FROM emp
4

2 に答える 2

7

いいえ、これには動的 SQL を使用する必要があります。

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = N'SELECT CAST(emp_id AS ' + Data_Type
 + ') FROM dbo.emp;'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'emp'
AND TABLE_SCHEMA = 'dbo' -- this might be important!
AND COLUMN_NAME = 'emp_id';

PRINT @sql;
-- EXEC sp_executesql @sql;

しかし、これは私には間違っているようです。列のデータ型がわからないのはなぜですか?

さらに、精度/スケール/最大長を考慮に入れる必要があるため、はるかに複雑なクエリが必要になります。たとえば、emp_idが のvarchar場合、すべての結果が 1 文字に切り捨てられます。

最後に、以上を強くお勧めsys.columnsINFORMATION_SCHEMAます。

于 2012-06-18T15:50:22.647 に答える
2

同様のことを行う必要があったため、動的 SQL に必要なリテラル データ型を返すことができるように関数を作成しました。このような関数が既に作成されているのを見つけることができなかったことに驚きました:(または、動的 SQL を介した CASTING は私の推奨ではそうではないので、驚くべきではありません...しかし、この時点では、ソーステーブルは変数です)

とにかく、これは誰もが必要とする機能です。これまでのところ、キャストしようとしているテーブルのデータ型のみを含めていることに注意してください...したがって、これを使用する人は誰でもそれに続き、必要なデータ型、またはおそらく残りのすべてのデータ型を含める必要があると思います.

CREATE FUNCTION dbo.GetLiteralDataType( @TableName as VARCHAR(100), @ColumnName as VARCHAR(100) )
    RETURNS VARCHAR(100)
    AS
    BEGIN

        DECLARE @DataType as VARCHAR(100)
        DECLARE @FullDataType as VARCHAR(100)
        DECLARE @MaxLength AS INT
        DECLARE @Precision AS INT
        DECLARE @Scale AS INT


        SET @DataType =(SELECT TOP 1 y.name FROM SYS.TABLES t
        INNER JOIN SYS.COLUMNS c ON t.object_id = c.object_id
        INNER JOIN SYS.TYPES y ON y.system_type_id = c.system_type_id
        WHERE t.name = @TableName AND c.name = @ColumnName)

        SET @MaxLength =(SELECT TOP 1 c.max_length FROM SYS.TABLES t
        INNER JOIN SYS.COLUMNS c ON t.object_id = c.object_id
        INNER JOIN SYS.TYPES y ON y.system_type_id = c.system_type_id
        WHERE t.name = @TableName AND c.name = @ColumnName)

        SET @Precision =(SELECT TOP 1 c.precision FROM SYS.TABLES t
        INNER JOIN SYS.COLUMNS c ON t.object_id = c.object_id
        INNER JOIN SYS.TYPES y ON y.system_type_id = c.system_type_id
        WHERE t.name = @TableName AND c.name = @ColumnName)

        SET @Scale =(SELECT TOP 1 c.scale FROM SYS.TABLES t
        INNER JOIN SYS.COLUMNS c ON t.object_id = c.object_id
        INNER JOIN SYS.TYPES y ON y.system_type_id = c.system_type_id
        WHERE t.name = @TableName AND c.name = @ColumnName)

        IF @DataType ='decimal'
        BEGIN
            SET @FullDataType = 'DECIMAL('+ @Precision + ',' + @Scale + ')'
        END

        IF @DataType ='varchar'
        BEGIN
            SET @FullDataType = 'VARCHAR('+ @MaxLength + ')'
        END

        IF @DataType ='bit'
        BEGIN
            SET @FullDataType = 'BIT'
        END

        IF @DataType ='money'
        BEGIN
            SET @FullDataType = 'MONEY'
        END

        IF @DataType ='date'
        BEGIN
            SET @FullDataType = 'DATE'
        END

        RETURN @FullDataType 
    END
于 2015-07-29T17:11:21.200 に答える