2
问题描述一个示例
假设我有这样一个表:CROSS JOIN一个表的列具有其数据
CREATE TABLE MyData(
Id INT PRIMARY KEY,
NotUniqueCol INT,
ColA NVARCHAR(128),
ColB NVARCHAR(128)
)
INSERT INTO MyData (Id, NotUniqueCol, ColA, ColB)
VALUES (1, 1, 'a', 'A')
, (2, 1, 'b', 'B')
, (3, 2, 'c', 'C')
和存储的过程,它需要一个表名,一个列名和列值:
CREATE PROCEDURE GetData
(
@tableName NVARCHAR(128),
@columnName NVARCHAR(128),
@id INT,
)
我执行它
EXEC GetData 'MyData', 'NotUniqueCol', 1
它应该返回是这样的:
RowNumber │ ColumnName │ ColumnValue
────────────┼────────────────┼──────────────────
1 │ 'Id' │ 1
1 │ 'NotUniqueCol' │ 1
1 │ 'ColA' │ 'a'
1 │ 'ColB' │ 'A'
2 │ 'Id' │ 2
2 │ 'NotUniqueCol' │ 1
2 │ 'ColA' │ 'b'
2 │ 'ColB' │ 'B'
大纲解决方案
的问题是GetData
的身体,因为一切都必须是通用的。
我的想法是下列步骤操作:
- 获取所有表名和他们一道,列和过滤结果。
- 执行一个动态查询,它从表中选择匹配的数据并计算行数。
- 做一个
CROSS JOIN
与2. UND 3.
步骤的结果1
SELECT c.[name]
FROM sys.tables AS t
INNER JOIN sys.columns AS c ON c.[object_id] = t.[object_id]
WHERE t.[name] = @tableName
步骤2
DECLARE @query NVARCHAR(MAX)
= ' SELECT ROW_NUMBER() OVER(ORDER BY myTable.' + QUOTENAME(@columnName) + ' DESC) AS [RowNumber], myTable.*'
+ ' FROM ' + QUOTENAME(@tableName) + ' AS myTable'
+ ' WHERE myTable.' + QUOTENAME(@columnName) + ' = ' + CAST(@id AS NVARCHAR(16))
PRINT @query
EXEC sp_sqlexec @query
使用游标获取结果
此代码有效,但由于光标我不喜欢。
-- The parameters from the SP
DECLARE @tableName NVARCHAR(128)='MyData',
@columnName NVARCHAR(128)='NotUniqueCol',
@id INT=1
--The body of the SP
CREATE TABLE #result (RowNumber INT, ColumnName NVARCHAR(128), ColumnValue SQL_VARIANT)
DECLARE @column NVARCHAR(128);
DECLARE myCursor CURSOR
FOR
SELECT c.[name]
FROM sys.tables AS t
INNER JOIN sys.columns AS c ON c.[object_id] = t.[object_id]
WHERE t.[name] = @tableName
OPEN myCursor
FETCH NEXT FROM myCursor
INTO @column
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @query NVARCHAR(MAX)
= ' SELECT ROW_NUMBER() OVER(ORDER BY myTable.' + QUOTENAME(@columnName) + ' DESC) AS [RowNumber], ''' + @column + ''' AS [ColumnName], myTable.' + QUOTENAME(@column)
+ ' FROM ' + QUOTENAME(@tableName) + ' AS myTable'
+ ' WHERE myTable.' + QUOTENAME(@columnName) + ' = ' + CAST(@id AS NVARCHAR(16))
PRINT @query
INSERT INTO #result(RowNumber, ColumnName, ColumnValue)
EXEC sp_sqlexec @query
FETCH NEXT FROM myCursor
INTO @column
END
CLOSE myCursor;
DEALLOCATE myCursor;
SELECT * FROM #result
ORDER BY RowNumber, ColumnName
DROP TABLE #result
最后一个问题
我还没有为步骤3不使用光标的好主意。它运作良好,但有没有使用CROSS JOIN
或其他的解决方案?
就是这样。谢谢! – Koopakiller
@Koopakiller对它有帮助 –