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
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
いいえ、これには動的 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.columns
しINFORMATION_SCHEMA
ます。
同様のことを行う必要があったため、動的 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