2

UNION ALL を使用して結合された複数の select ステートメントがあります。例:

Select col1,col2,...,coln from A
UNION ALL
Select Col1,Col2,...,coln from B

2 番目のテーブルの列の 1 つに間違った値があり、クエリを実行するとエラーが発生します。

Msg 241, Level 16, State 1, Line 1
Conversion failed when converting date and/or time from character string.

問題の原因となっている列/行を特定するのが困難で、多くの列があり、エラーは特に何も言いません。エラーを追跡できる例を教えてください。前もって感謝します!!!

4

1 に答える 1

0

これら 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
*/
于 2013-01-24T20:33:28.310 に答える