2

我有一个使用 UNION ALL 组合在一起的多重选择语句。例如:

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

第二个表中的一列具有错误的值,执行查询时出现错误。

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

我很难确定是哪一列/行导致了问题,它有很多列,并且错误没有具体说明什么。有人可以给我一个例子,我可以追踪错误。先感谢您!!!

4

1 回答 1

0

您可以尝试比较这两个 SELECT 的元数据的脚本。为了获取元数据信息,我使用了 sp_describe_cursor_columns系统过程(使用起来不太好 - true;在 SQL Server 2008 中可用),因为sp_describe_first_result_set从 SQL Server 2012 开始可用。

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 回答