我需要在存储过程的最后SELECT
语句中重新排序列。列订单需要从另一个表中获取。
我有一个基于动态SQL的解决方案。有没有更好的方法呢?我有大约100列返回,有数百万行用于Excel导出。除了动态查询之外,还有其他任何性能优化解决方案吗?
请在下面找到我当前解决方案的示例代码。
IF OBJECT_ID( 'tempdb..#TempColumns') IS NOT NULL
BEGIN
DROP TABLE #TempColumns
END
IF OBJECT_ID( 'tempdb..#TempColumnsOrder') IS NOT NULL
BEGIN
DROP TABLE #TempColumnsOrder
END
CREATE TABLE #TempColumns
(
ID INT IDENTITY,
FirstName VARCHAR(MAX),
LastName VARCHAR(MAX),
Gender VARCHAR(MAX)
)
INSERT INTO #TempColumns
VALUES ('ABC', 'DEF', 'MALE'), ('PR', 'ZA', 'FEMALE'), ('ERT', 'GFG', 'MALE')
CREATE TABLE #TempColumnsOrder
(
ID INT IDENTITY,
ColumnName VARCHAR(MAX),
ColumnOrder INT
)
INSERT INTO #TempColumnsOrder
VALUES ('FirstName', 3), ('LastName', 2), ('Gender', 1)
SELECT * FROM #TempColumns
SELECT * FROM #TempColumnsOrder
DECLARE @script VARCHAR(MAX)
SELECT @script = 'SELECT '
SELECT @script = @script + ColumnName + ','
FROM #TempColumnsOrder
ORDER BY ColumnOrder
PRINT @script
SELECT @script = SUBSTRING(RTRIM(@script), 1, LEN(RTRIM(@script)) - 1)
SELECT @script = @script + ' FROM #TempColumns'
EXEC (@script)
IF OBJECT_ID( 'tempdb..#TempColumns') IS NOT NULL
BEGIN
DROP TABLE #TempColumns
END
IF OBJECT_ID( 'tempdb..#TempColumnsOrder') IS NOT NULL
BEGIN
DROP TABLE #TempColumnsOrder
END
答案 0 :(得分:0)
感谢您的回复,除了我做的事情之外,动态SQL还有更好的方法吗?
您可以消除您正在使用的不受支持的字符串连接,并简化代码的现代化:
DROP TABLE IF EXISTS #TempColumns
DROP TABLE IF EXISTS #TempColumnsOrder
CREATE TABLE #TempColumns
(
ID INT IDENTITY,
FirstName VARCHAR(MAX),
LastName VARCHAR(MAX),
Gender VARCHAR(MAX)
)
INSERT INTO #TempColumns
Values('ABC','DEF','MALE'),('PR','ZA','FEMALE'),('ERT','GFG','MALE')
CREATE TABLE #TempColumnsOrder
(
ID INT IDENTITY,
ColumnName VARCHAR(MAX),
ColumnOrder INT
)
INSERT INTO #TempColumnsOrder
Values('FirstName',3), ('LastName',2), ('Gender',1)
SELECT * FROM #TempColumns
SELECT * FROM #TempColumnsOrder
DECLARE @script VARCHAR(MAX) = concat(
'SELECT ',
(select STRING_AGG(QUOTENAME(ColumnName),', ') WITHIN GROUP (ORDER BY ColumnOrder)
FROM #TempColumnsOrder),
' FROM #TempColumns')
print @script
EXEC (@script)
DROP TABLE IF EXISTS #TempColumns
DROP TABLE IF EXISTS #TempColumnsOrder
答案 1 :(得分:0)
SELECT @script = @script + ColumnName +','FROM #TempColumnsOrder 订单按ColumnOrder
无法保证聚合字符串连接与上述技术的行为。实际行为取决于计划,因此您可能无法获得所需的结果。
在SQL Server 2017和Azure SQL数据库中,STRING_AGG
是正确的方法:
SELECT STRING_AGG(ColumnName, ',') WITHIN GROUP(ORDER BY ColumnOrder)
FROM #TempColumnsOrder;
在SQL Server 2012等较旧的SQL版本中,最好的方法是使用XML PATH()
:
SELECT @script = @script +
STUFF((SELECT ',' + ColumnName
FROM #TempColumnsOrder
ORDER BY ColumnOrder
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'');
有关上述查询如何运作的详细信息,请参阅this answer。