これら 2 つの SELECT のメタデータを比較するこのスクリプトを試すことができます。sp_describe_first_result_setは SQL Server 2012 以降で使用できるため、メタデータ情報を取得するために、sp_describe_cursor_columnsシステム プロシージャを使用しました (これはあまり使い心地がよくありません。SQL Server 2008 で使用できます) 。
SET NOCOUNT ON;
DECLARE @Metadata TABLE (
select_num tinyint NOT NULL,
check (select_num IN (1,2)),
ordinal_position int not null,
primary key (select_num, ordinal_position),
column_name sysname,
column_size int,
data_type_sql smallint,
column_precision tinyint,
column_scale tinyint
)
DECLARE
@column_name sysname,
@ordinal_position int,
@column_characteristics_flags int,
@column_size int,
@data_type_sql smallint,
@column_precision tinyint,
@column_scale tinyint,
@order_position int,
@order_direction varchar(1),
@hidden_column smallint,
@columnid int,
@objectid int,
@dbid int,
@dbname sysname
DECLARE @ReturnSelect CURSOR
-- Metadata for the first query
DECLARE CursorSelect1 CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT TOP(0) ...
FROM A ...
OPEN CursorSelect1
EXEC sp_describe_cursor_columns @cursor_return=@ReturnSelect OUTPUT, @cursor_source='local', @cursor_identity=N'CursorSelect1'
WHILE (1=1)
BEGIN
FETCH NEXT FROM @ReturnSelect INTO
@column_name,
@ordinal_position,
@column_characteristics_flags,
@column_size,
@data_type_sql,
@column_precision,
@column_scale,
@order_position,
@order_direction,
@hidden_column,
@columnid,
@objectid,
@dbid,
@dbname
IF @@FETCH_STATUS=0
BEGIN
INSERT @Metadata (select_num, ordinal_position, column_name, data_type_sql, column_size, column_precision, column_scale)
VALUES (1, @ordinal_position, @column_name, @data_type_sql, @column_size, @column_precision, @column_scale); -- First SELECT
END
ELSE
BEGIN
BREAK
END
END
CLOSE CursorSelect1
DEALLOCATE CursorSelect1
CLOSE @ReturnSelect
DEALLOCATE @ReturnSelect
-- End of Metadata for the first query
-- Metadata for the second query
DECLARE CursorSelect2 CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT TOP(0) ...
FROM B ...
OPEN CursorSelect2
EXEC sp_describe_cursor_columns @cursor_return=@ReturnSelect OUTPUT, @cursor_source='local', @cursor_identity=N'CursorSelect2'
WHILE (1=1)
BEGIN
FETCH NEXT FROM @ReturnSelect INTO
@column_name,
@ordinal_position,
@column_characteristics_flags,
@column_size,
@data_type_sql,
@column_precision,
@column_scale,
@order_position,
@order_direction,
@hidden_column,
@columnid,
@objectid,
@dbid,
@dbname
IF @@FETCH_STATUS=0
BEGIN
INSERT @Metadata (select_num, ordinal_position, column_name, data_type_sql, column_size, column_precision, column_scale)
VALUES (2, @ordinal_position, @column_name, @data_type_sql, @column_size, @column_precision, @column_scale); -- Second SELECT
END
ELSE
BEGIN
BREAK
END
END
CLOSE CursorSelect2
DEALLOCATE CursorSelect2
-- End of Metadata for the second query
CLOSE @ReturnSelect
DEALLOCATE @ReturnSelect
SELECT s1.*, s2.*
FROM (
SELECT m.*, t.name AS user_type_name
FROM @Metadata m JOIN sys.types t ON m.data_type_sql=t.user_type_id
WHERE select_num=1
) s1 -- metadata for the first SELECT
INNER JOIN (
SELECT m.*, t.name AS user_type_name
FROM @Metadata m JOIN sys.types t ON m.data_type_sql=t.user_type_id
WHERE select_num=2
) s2 -- metadata for the second SELECT
ON s1.ordinal_position=s2.ordinal_position
WHERE s1.data_type_sql<>s2.data_type_sql -- It compares the data type for every column from these two SELECT queries
/*
-- or
SELECT s1.*, s2.*
FROM (SELECT m.*, t.name AS user_type_name FROM @Metadata m JOIN sys.types t ON m.data_type_sql=t.user_type_id WHERE select_num=1) s1 -- metadata for the first SELECT
FULL OUTER JOIN (SELECT m.*, t.name AS user_type_name FROM @Metadata m JOIN sys.types t ON m.data_type_sql=t.user_type_id WHERE select_num=2) s2 -- metadata for the second SELECT
ON s1.ordinal_position=s2.ordinal_position
WHERE s1.ordinal_position=s2.ordinal_position
AND s1.data_type_sql<>s2.data_type_sql -- It compares the data type for every column from these two SELECT queries
OR s1.ordinal_position IS NOT NULL AND s2.ordinal_position IS NULL
OR s1.ordinal_position IS NULL AND s2.ordinal_position IS NOT NULL
*/