我正在编写一个查询来旋转表格元素,其中列名是动态生成的。
SET @query = N'SELECT STUDENT_ID, ROLL_NO, TITLE, STUDENT_NAME, EXAM_NAME, '+
@cols +
' INTO ##FINAL
FROM
(
SELECT *
FROM #AVERAGES
UNION
SELECT *
FROM #MARKS
UNION
SELECT *
FROM #GRACEMARKS
UNION
SELECT *
FROM #TOTAL
) p
PIVOT
(
MAX([MARKS])
FOR SUBJECT_ID IN
( '+
@cols +' )
) AS FINAL
ORDER BY STUDENT_ID ASC, DISPLAYORDER ASC, EXAM_NAME ASC;'
EXECUTE(@query)
select * from ##FINAL
此查询在我的本地数据库中正常工作,但它在SQL Azure中不起作用,因为那里不允许使用全局临时表。
现在,如果我在本地数据库中将##FINA
L更改为#FINAL
,但它会给我带来错误
无效的对象名称'#FINAL'。
如何解决此问题?
答案 0 :(得分:10)
好吧,在说我不认为可以做到之后,我可能会有办法。虽然这很难看。希望您可以使用下面的示例并根据您的查询进行调整(没有您的架构和数据,这对我来说太难以尝试编写):
declare @cols varchar(max)
set @cols = 'object_id,schema_id,parent_object_id'
--Create a temp table with the known columns
create table #Boris (
ID int IDENTITY(1,1) not null
)
--Alter the temp table to add the varying columns. Thankfully, they're all ints.
--for unknown types, varchar(max) may be more appropriate, and will hopefully convert
declare @tempcols varchar(max)
set @tempcols = @cols
while LEN(@tempcols) > 0
begin
declare @col varchar(max)
set @col = CASE WHEN CHARINDEX(',',@tempcols) > 0 THEN SUBSTRING(@tempcols,1,CHARINDEX(',',@tempcols)-1) ELSE @tempcols END
set @tempcols = CASE WHEN LEN(@col) = LEN(@tempcols) THEN '' ELSE SUBSTRING(@tempcols,LEN(@col)+2,10000000) END
declare @sql1 varchar(max)
set @sql1 = 'alter table #Boris add [' + @col + '] int null'
exec (@sql1)
end
declare @sql varchar(max)
set @sql = 'insert into #Boris (' + @cols + ') select ' + @cols + ' from sys.objects'
exec (@sql)
select * from #Boris
drop table #Boris
它们的关键是在外部作用域中创建临时表,然后内部作用域(在EXEC
语句中运行的代码)可以访问相同的临时表。以上工作在SQL Server 2008上,但我没有可以使用的Azure实例,所以没有在那里测试。
答案 1 :(得分:1)
如果你创建了一个临时表,它可以从你的spid中执行的动态sql中看到,如果你在动态sql中创建表,那么它就不可见了。
有一种解决方法。您可以创建存根表并在动态sql中更改它。它需要一些字符串操作,但我已经使用这种技术为tsqlunit生成动态数据集。
CREATE TABLE #t1
(
DummyCol int
)
EXEC(N'ALTER TABLE #t1 ADD foo INT')
EXEC ('insert into #t1(DummyCol, foo)
VALUES(1,2)')
EXEC ('ALTER TABLE #t1 DROP COLUMN DummyCol')
select *from #t1