此数据库的模式为奇数;所有数据均按数据类型分解并存储在相应的表中。当需要访问“表”时,需要将其缝在一起,按表ID组合字段,按字段ID组合值。它运行缓慢,并且很大程度上已由第三方意大利面条脚本处理。
我有些表格的格式如下:
dbo.TagSource:
TagSourceId | Table Name | ...
------------------------------------
01 Table 1
02 Table 2
dbo.Tag:
TagId | TagSourceId | Field Name | RawTableName | ...
------------------------------------------------------
11 01 Name dbo.StringValue
12 01 Age dbo.IntegerValue
13 01 Balance dbo.DecimalValue
14 01 Document dbo.FileValue
15 02 Name ExternalTable1
16 02 Height ExternalTable1
17 02 Occupation ExternalTable2
dbo。[字符串/整数/小数/文件/ ...]值表:
ValueId | TagId | Value
-------------------------------
101 11 John Smith
102 11 Jane Smith
103 11 John Doe
104 11 Jane Doe
105 11 Thanos
目标:要创建以TagSourceID作为参数/声明的变量的TSQL查询脚本(存储过程/函数/视图),请返回相应的表。最终,它将用于创建视图,直到我有足够的带宽来替换和替换此数据库架构为止。
实现此目的的最佳方法是什么?这是一个挑战,因为每个表中的字段数是动态的,并且列定义是未知的。
尝试: 我曾尝试使用临时表来保存我的汇总数据和要追加的数据,但是很快发现,由于必须预定义列定义,因此我不得不在临时表之间使用笨拙的数据处理方法。似乎是次优的,即使它起作用,也没有。
逻辑:
BEGIN LOOP
#B = #A Join (Select value From dbo...Value Table...)
Drop Table #A
#A = #B
Drop Table #B
END
脚本:
即使我已明确There is already an object named '#ResultSet' in the database.
错误行之前的行,也会返回错误DROP TABLE #ResultSet
。
--*** DECLARATION ***
USE [DB_Arc];
GO
-- ***************
-- Target Table Id
DECLARE @TagSourceID INT = 130;
-- ***************
-- Temporary Tables - DROP IF EXIST
-- #TempA
IF OBJECT_ID(N'#ResultSet') IS NOT NULL DROP TABLE #ResultSet;
CREATE TABLE dbo.#ResultSet (
DateTime DATETIME,
GroupID NVARCHAR(50)
);
-- #TempB
IF OBJECT_ID(N'#JoinSet') IS NOT NULL DROP TABLE #JoinSet;
CREATE TABLE dbo.#JoinSet (
DateTime DATETIME,
GroupID NVARCHAR(50)
);
-- Target Fields - Iterator
DECLARE field_cursor CURSOR FOR
SELECT Id, Name, RawTableName
FROM dbo.[Tag]
WHERE TagSourceId = @TagSourceID
AND Name NOT IN ('DateTime','GroupId')
AND TagTypeId NOT IN (6,7)
ORDER BY Id;
-- Local Variables
DECLARE @TagId bigint, @TagName nvarchar(250), @RawTableName nvarchar(250)
OPEN field_cursor;
-- Initial first fetch and store
FETCH NEXT FROM field_cursor
INTO @Tag, @TagName, @RawTableName;
-- Verify that the table where the values are stored is not external.
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @RawTableName)
BEGIN --IF BLOCK
-- Check @@FETCH_STATUS for any other rows to fetch
WHILE @@FETCH_STATUS = 0
-- Loop through each field/column...
BEGIN --LOOP START
-- full outer join values from rawtables to ResultSet
-- #TempB = #TempA Join (Select value From dbo...Value Table...)
DECLARE @field nvarchar(500);
SET @field =
N'SELECT a.*, b.value AS ' + QuoteName(@TagName) +
N'INTO #JoinSet
FROM #ResultSet a
FULL OUTER JOIN (
SELECT
CONVERT(datetime2, [DateTime], 1) as DateTime,
[GroupId],
[Value]
FROM dbo.' + QuoteName(@RawTableName) +
N'WHERE TagId = ' + QuoteName(@TagId) + N'AND
IsDeleted=0 ) b
ON a.DateTime = b.DateTime AND a.GroupId = b.GroupId
';
EXEC sp_executesql @field;
-- DROP TABLE #TempA
IF OBJECT_ID(N'#ResultSet') IS NOT NULL DROP TABLE #ResultSet
-- #TempA = #TempB
-- ***** ERROR BLOCK START *****
-- Returns 'There is already an object named '#ResultSet' in the database.'
SELECT *
INTO #ResultSet
FROM #JoinSet;
-- ***** ERROR BLOCK END *****
-- DROP TABLE #TempB
DROP TABLE #JoinSet;
-- Iterate values to next field
FETCH NEXT FROM field_cursor
INTO @Tag, @TagName, @RawTableName;
END --LOOP END
END --IF BLOCK END
CLOSE field_cursor;
DEALLOCATE field_cursor;
SELECT * FROM #ResultSet;
DROP TABLE #ResultSet;
GO
我也一直在寻找创建一个递归过程/函数来处理此问题,但是我在使用游标作为递归条件时遇到了麻烦,并且具有静态列定义的表变量/临时表仍然是一个问题。
任何帮助将不胜感激。如果您对此脚本的用途有疑问或有任何一般性建议,我非常希望听到它。
答案 0 :(得分:1)
脚本中的三个问题-