【问题标题】:SQL Server - Dynamic SQL View Generation (currently using cursor)SQL Server - 动态 SQL 视图生成(当前使用游标)
【发布时间】:2014-03-13 06:43:50
【问题描述】:

环境: SQL Server 2008 R2。无法访问正确的工具(sql server management studio 等)。必须在活动管理 GUI 的高级 sql 选项卡中创建(因此只能通过查看日志来查看问题所在!)。

问题:我正在尝试创建一个动态 sql 视图,该视图引用了许多临时表,这些临时表的表名列在系统表中。我的背景是 oracle 和 VBA,我对 SQL Server 了解不多。我需要动态执行此操作的原因是,每次在 GUI 中更新段时,后端临时表名称都会更改。所以我需要一个按需例程,让我知道他们的时间点临时表名称是什么。

我想在过程中创建的视图(可以根据前缀为“%EX_MBR%”的表的数量而变化)

    Create view dbo.VW_Exclusions_Matrix as select a.durable_mbr_acc_id
,case when TB_EX_MBR_COMPLAINTS.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_COMPLAINTS
,case when TB_EX_MBR_DECEASED.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DECEASED
,case when TB_EX_MBR_DO_NOT_EMAIL.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DO_NOT_EMAIL
,case when TB_EX_MBR_DO_NOT_MAIL.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DO_NOT_MAIL
,case when TB_EX_MBR_DO_NOT_MARKET_ALL.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DO_NOT_MARKET_ALL
,case when TB_EX_MBR_DO_NOT_PHONE.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DO_NOT_PHONE
,case when TB_EX_MBR_DO_NOT_SMS.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_DO_NOT_SMS
,case when TB_EX_MBR_EMAIL_BOUNCE_HARD.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_EMAIL_BOUNCE_HARD
,case when TB_EX_MBR_EMAIL_BOUNCE_SOFT.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_EMAIL_BOUNCE_SOFT
,case when TB_EX_MBR_FIN_PLAN_REFERRAL.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_FIN_PLAN_REFERRAL
,case when TB_EX_MBR_NO_CONTRIBS_12MTHS.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_NO_CONTRIBS_12MTHS
,case when TB_EX_MBR_INVALID_TFN.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_INVALID_TFN
,case when TB_EX_MBR_OVERSEAS.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_OVERSEAS
,case when TB_EX_MBR_STAFF.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_STAFF
,case when TB_EX_MBR_RESEARCH_OPT_OUT.durable_mbr_acc_id is null then 'N' ELSE 'Y' END AS EX_MBR_RESEARCH_OPT_OUT
from (dbo.UACS_1843_y a LEFT JOIN dbo.uacs_1799_1m TB_EX_MBR_COMPLAINTS on a.durable_mbr_acc_id = TB_EX_MBR_COMPLAINTS.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1n TB_EX_MBR_DECEASED on (a.durable_mbr_acc_id = TB_EX_MBR_DECEASED.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1o TB_EX_MBR_DO_NOT_EMAIL on (a.durable_mbr_acc_id = TB_EX_MBR_DO_NOT_EMAIL.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1p TB_EX_MBR_DO_NOT_MAIL on (a.durable_mbr_acc_id = TB_EX_MBR_DO_NOT_MAIL.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1q TB_EX_MBR_DO_NOT_MARKET_ALL on (a.durable_mbr_acc_id = TB_EX_MBR_DO_NOT_MARKET_ALL.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1r TB_EX_MBR_DO_NOT_PHONE on (a.durable_mbr_acc_id = TB_EX_MBR_DO_NOT_PHONE.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1t TB_EX_MBR_DO_NOT_SMS on (a.durable_mbr_acc_id = TB_EX_MBR_DO_NOT_SMS.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1u TB_EX_MBR_EMAIL_BOUNCE_HARD on (a.durable_mbr_acc_id = TB_EX_MBR_EMAIL_BOUNCE_HARD.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1v TB_EX_MBR_EMAIL_BOUNCE_SOFT on (a.durable_mbr_acc_id = TB_EX_MBR_EMAIL_BOUNCE_SOFT.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1w TB_EX_MBR_FIN_PLAN_REFERRAL on (a.durable_mbr_acc_id = TB_EX_MBR_FIN_PLAN_REFERRAL.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1j TB_EX_MBR_NO_CONTRIBS_12MTHS on (a.durable_mbr_acc_id = TB_EX_MBR_NO_CONTRIBS_12MTHS.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1s TB_EX_MBR_INVALID_TFN on (a.durable_mbr_acc_id = TB_EX_MBR_INVALID_TFN.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1x TB_EX_MBR_OVERSEAS on (a.durable_mbr_acc_id = TB_EX_MBR_OVERSEAS.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1799_1y TB_EX_MBR_STAFF on (a.durable_mbr_acc_id = TB_EX_MBR_STAFF.durable_mbr_acc_id)
LEFT JOIN dbo.uacs_1861_c TB_EX_MBR_RESEARCH_OPT_OUT on (a.durable_mbr_acc_id = TB_EX_MBR_RESEARCH_OPT_OUT.durable_mbr_acc_id)

该视图当前是使用 Excel 公式创建的,并且可以正常工作。我正在尝试在下面的过程中重新创建公式逻辑......但我不知道我在做什么。

首先进入程序(我还需要程序吗?)

CREATE PROCEDURE GenerateExclusionMatrix
AS
SET NOCOUNT ON;

Declare @sqAll nvarchar(8000), @sq1 nvarchar(1000), @sq2 nvarchar(1000), @UnicaBase varchar(100), @UnicaFieldName nvarchar(100), @UnicaTempTable nvarchar(100), @TableAlias nvarchar(100), @cnt int := 0;
Declare curP cursor For select Name as Var_FieldName, TempTableName as Var_UnicaTempTable, Name as Var_TableAlias FROM dbo.UA_Segment WHERE dbo.UA_Segment.name like '%EX_MBR%' and activeflag = 1;

SET @sq1 = ''
SET @sq2 = ''

@sq1 = 'CREATE VIEW dbo.VW_EXCLUSIONS_MATRIX AS SELECT a.durable_mbr_acc_id '

OPEN curP 
Fetch Next From curP Into @UnicaFieldName, @UnicaTempTable, @TableAlias

While @@Fetch_Status = 0 Begin

SET @UnicaBase = (select distinct TempTableName as Var_UnicaBase FROM dbo.UA_Segment a WHERE a.name = 'IN_MBR_ACTIVE_OR_DEEMED' and ActiveFlag = 1)

open cursor

@cnt := @cnt + 1;
@sq1 := @sq1 + ',case when TB_' + @TableAlias + '.durable_mbr_acc_id is null then '''N''' ELSE '''Y''' END AS ' + @UnicaFieldName                       

IF (@cnt = 1)      
    @sq2 := @sq2 + ' from (dbo.UACS' + @UnicaBase + ' a LEFT JOIN dbo.UACS' + @UnicaTempTable + ' TB_' + @TableAlias + ' on a.durable_mbr_acc_id = TB_' + @TableAlias + '.durable_mbr_acc_id)'
ELSE
    @sq2 := @sq2 + ' LEFT JOIN dbo.UACS' + @UnicaTempTable + ' TB_' + @TableAlias + ' on (a.durable_mbr_acc_id = TB_' + @TableAlias + '.durable_mbr_acc_id)'
END IF

Fetch Next From curP Into  @UnicaFieldName, @UnicaTempTable, @TableAlias
End 

@sq1 = @sq1 + @sq2 

Close curP

Deallocate curP

    exec sp_executesql @sq1

END;

我希望这是有道理的。非常感谢任何帮助。

干杯,

詹姆斯


在反馈后更新语法 - 2014 年 2 月 14 日下午 3:11


【问题讨论】:

  • “无法使用正确的工具” - 安装免费版的 SSMS
  • 我只是不明白为什么你需要一个光标来创建这个视图。使用 COALESCE 函数将其封装在单个查询中会更快、更优雅。
  • 嗨,米奇,我有 SSMS,但我可以访问数据库,因为有一些我不应该看到的数据……需要几天时间。我可以在没有 db 的情况下使用它来测试语法吗?尼扎姆你能举个例子吗?以为我需要一个循环来添加每个新行来生成 SQL。正如我所说...我知道如何以其他方式执行此操作...只是不在 SQL Server 中。

标签: sql-server stored-procedures dynamic cursor sql-view


【解决方案1】:

我无法测试代码,但您可以尝试一些不使用游标的方法(这里不需要它们)

CREATE PROCEDURE GenerateExclusionMatrix 
AS  

   DECLARE @UnicaBase nvarchar(100) 
   SET @UnicaBase = (select TempTableName as Var_UnicaBase FROM dbo.UA_Segment a WHERE a.name = 'IN_MBR_ACTIVE_OR_DEEMED' and ActiveFlag = 1)

   DECLARE @SQL1 NVARCHAR(MAX) = 'CREATE VIEW dbo.VW_EXCLUSIONS_MATRIX AS SELECT a.durable_mbr_acc_id '
   select @SQL1 = @SQL1 + ',case when TB_' + Name + '.durable_mbr_acc_id is null then ''N'' ELSE ''Y'' END AS ' + Name
   FROM dbo.UA_Segment 
   WHERE dbo.UA_Segment.name like '%EX_MBR%' and activeflag = 1;


   DECLARE @SQL2 NVARCHAR(MAX) = 'from (dbo.UACS' + @UnicaBase + ' a '
   select @SQL2 = @SQL2 + ' LEFT JOIN dbo.UACS' + TempTableName + ' TB_' + Name + ' on a.durable_mbr_acc_id = TB_' + Name + '.durable_mbr_acc_id'
   FROM dbo.UA_Segment 
   WHERE dbo.UA_Segment.name like '%EX_MBR%' and activeflag = 1;

   DECLARE @SQL NVARCHAR(MAX)
   SET @SQL = @SQL1 + @SQL2 


   exec sp_executesql @sq1

END;

UPDATE:我无法运行,但是可以在中查看生成的要创建的动态sql http://sqlfiddle.com/#!3/bc9a9/1/0

【讨论】:

  • 您好 Nizam,非常感谢您的回答。我不确定这会奏效吗?我已更新我的帖子以显示我正在尝试创建的完整视图。我在想我需要使用循环构建一个视图,并在每个循环之后添加对新表的引用。我认为您刚刚解决了我显示的简化视图?谢谢詹姆斯
  • 看看我提供的链接。我很确定你可以在没有游标的情况下做到这一点,只需要在表中包含动态构造的值。代码可能需要一些调整,因为我无法测试它。请注意,我必须硬编码设置变量 @UnicaBase 的值。
  • 您好 Nizam,感谢您的链接。 SQL Fiddle 看起来真的很有用。您是否注意到我在上面的修改后的帖子中显示了完整的 sql 视图?这会改变事情吗?因为在我看来,您的代码无法解释更改 TempTableNames 包括增加/减少我必须引用的数字?
  • @user3308676:我已更新链接以表明此查询足够灵活,可以回答您的问题
  • Brilliant Nizam...非常感谢。我应该用您在 SQL Fiddle 中创建的代码更新您的回复吗?太聪明了,我仍在努力追随它...从历史上看,我总是会循环执行此操作...在那里我可以看到“循环”一词(或等效词)!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2018-06-01
相关资源
最近更新 更多