【发布时间】:2013-10-18 20:42:09
【问题描述】:
动态创建表,然后将我创建的所有表连接在一起的好方法是什么?
背景
我正在尝试编写一个存储过程,该过程从数据库的各个部分收集数据并将其呈现以供使用。例如,如果我想向 Alice 和 Bob 发送发票,这个存储过程将找到发票的所有信息。诀窍是爱丽丝和鲍勃并不总是需要我拥有的所有信息。如果 Bob 是免税的,但交易的是 simoleons,我需要包含有关货币汇率的信息,但忽略税收信息。我想给存储过程一个订单号,然后将格式化的结果返回给客户。
到目前为止,我的解决方案是创建一个包含客户要求的表格。然后我的存储过程检查表:如果需要货币数据,我创建并填充@Currency,或者@Taxes 保存税收数据等等。我检查了要求,然后根据需要创建表。最后,我需要将数据加入一个记录集。
我的问题是我说错了
关键字“table”附近的语法不正确
和一个错误说
必须声明表变量@Summary
在我定义 @Summary 的第 1 行上,这些错误仅在我使用动态 SQL 连接表时出现。当我注释掉动态 SQL 并将语句复制粘贴到它应该创建的语句中时,我得到了我想要的结果。
代码
我尝试在 Microsoft SQL Server Management Studio 中使用以下动态 SQL
create procedure <procedure> (@OrderNumber varchar(20)) AS
DECLARE @CustomerName varchar(35) -- retrieved based on @OrderNumber
DECLARE @SQLQuery nvarchar(500)
DECLARE @ParamDef nvarchar(500)
DECLARE @SummaryTable table
(
ID varchar(20) --=@OrderNumber
, <Stuff>
)
SET @SQLQuery = 'Select * From @SummaryTable'
SET @ParamDef = '@SummaryTable table'
IF EXISTS(Select <TableName> from CustRequirements where <TableName> = 1 AND Customer = @CustomerName)
BEGIN
--Create table
DECLARE @<TableName> table
(
ID varchar(20)
, <Stuff>
)
--Populate
Insert into <TableName> Select <RelevantData> From <DataSource> where <Condition based on @OrderNumber or @CustomerName>
--Pepare Dynamic SQL
Set @SQLQuery = @SQLQuery + ' FULL OUTER JOIN @<TableName> ON <TableName>.ID = SummaryTable.ID'
SET @ParamDef = ', @<TableName> table'
END
<repeat for other tables>
EXECUTE sp_executesql @SQLQuery, @ParamDef, @Summary, @LineItems, @Taxes, @Currency
问题
我的代码有问题吗?有一个更好的方法吗?我想到的另一个选择是在每个分支的底部使用带有 entire JOIN 语句的 IF Exists 树(因为我似乎无法用 IF 中断 JOIN 子句)。问题是我需要 2^n JOIN 语句来加入 n 个可能的表。在这种情况下,n 可能与 20 或 30 一样高。
【问题讨论】:
-
我认为您的做法不太正确。不同的观点...尝试将每个用户视为过滤器,而不是一组不同的表连接。创建完全连接所有内容的完整 SQL 语句...使用 where 子句根据用户过滤行,并使用 case 语句根据用户需求表中的用户信息过滤掉列
-
感谢您的回复。我会考虑这一点,尽管我不确定在这种情况下我能做到这一点。
表很大,所以我会担心基本上将数据库中的每个表连接成一个巨大的怪物,然后选择我需要的位。 -
我认为最好的方法是使用您现有的表格。
标签: sql sql-server sql-server-2008 join dynamic-sql