"Down" 在执行全部并集时强制转换列 (MS SQL Server 2012)



根据在(https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-2017(中找到的SQL类型转换图表,我使用的所有数据类型都可以隐式转换为nvarchar类型。 这对我的目的来说是理想的,因此我希望这会起作用,认为 #CSV_Column_Titles 将确定所有列的类型:

INSERT INTO #CSV_Output          
SELECT * from #CSV_Column_Titles   --  n" columns, all columns are nvarchar( MAX ) )
UNION ALL
SELECT * FROM #QueryResults       --  "n" columns, all must be implicitly converted to nvarchar( MAX )

但是,这将返回如下消息:

Msg 8114, Level 16, State 5, Line 120
Error converting data type nvarchar to float.

我知道为什么会发生这种情况;对于我试图做的事情,转换优先级规则(见 https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-2017(是"向后"的。我预计隐式转换将从最具体/限制性的形式"向下抛弃"到最一般的形式 - 这将满足我的需求。

上面的代码片段来自创建"CSV 样式"表的过程。 隐式转换(到 nvarchar(将是理想的,因为 #QueryResults 作为参数传入,并且可以具有任意数量的任何类型的列。 (对于那些好奇的人,#CSV_Column_Titles 是通过使用动态 SQL 从 #QueryResults 中提取列标题来创建的。

我试图通过创建一个使用的已定义类型(nvarchar 的别名(来解决优先级问题,但被拒绝了"创建"权限(并且知道它永远不会被授予(。

在我进一步研究使用动态 SQL 之前,是否有一些简单的方法(理想情况下隐式(将每列"向下转换"到 nvarchar,而不必使用显式强制转换/转换?


顺便说一句,如果我必须动态sql,我看到它做类似的事情(这是概念性的,而不是实际的SQL代码(:

INSERT INTO #CSV_Output          
SELECT * from #CSV_Column_Titles   
UNION ALL
EXECUTE( @Command )          -- instead of SELECT * FROM #QueryResults

其中@Command正在构建如下:

Set @Command  =  'SELECT (CAST(' +  @ColumnName + ' ) as nvarchar (MAX)) as '' +  @ColumnName  +'' '

然后为 #QueryResults 的其余每一列附加以下行之一:

Set @Command =  @Command + ' , (CAST(' + @ColumnName + ' ) as nvarchar (MAX)) as '' + @ColumnName  + '' '

并以

Set @Command =   @Command + ' FROM #QueryResults' )

其中@ColumnName是从用于创建 #CSV_Column_Titles 的临时表中提取的。


更新20180404

(叹息(在激烈的战斗中,你往往看不到树木的森林...... 我犯了两个错误:假设联合中的第一个 Select * 将(隐式地(确定最终结果集的列类型,并试图一步完成很多事情。

接受答案的关键点是在进行联合之前进行转换。

就我而言,不需要联合,我所要做的就是将(转换后的(值插入 #CSV_Output 并将其传递回调用脚本。

如果您不介意额外的 I/O,则可以在没有动态 SQL 的情况下执行此操作。

首先,使用输出表的架构创建一个临时表(使用带有负谓词的 SELECT/INTO(。将查询 #2 插入到此临时表中,以便它将隐式转换为这些目标类型。在您的情况下,这都是NVARCHAR(MAX(。

--This will create a table like #CSV_Output, to store intermediate results
SELECT * INTO #QueryResultsCast FROM #CSV_Output WHERE 0 = 1
--cast all via INSERT
INSERT INTO #QueryResultsCast
SELECT * FROM #QueryResults
--Original desired output (retrieving from #QueryResultsCast)
INSERT INTO #CSV_Output          
SELECT * from #CSV_Column_Titles   --  n" columns, all columns are nvarchar( MAX ) )
UNION ALL
SELECT * FROM #QueryResultsCast       --  "n" columns, all must be implicitly converted to nvarchar( MAX )

最新更新