【问题标题】:Use Dynamic Syntax in a View or a Function在视图或函数中使用动态语法
【发布时间】:2016-07-22 17:56:27
【问题描述】:

我编写了一个动态查询,如下所示:

DECLARE @sql nvarchar(max)


SELECT @sql = 
'select distinct datetable.Date 
from (
select cast(DATEADD(day,-(a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)),getdate()) as date) AS Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a

cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b

cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c

 cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d

 union all 

 select cast(DATEADD(day,(a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)),getdate()) as date) AS Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a

cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b

cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c

 cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d
) datetable
where '
+
replace(replace(replace(stuff((SELECT ' or datetable.Date between cast(''' + cast(cast(hld1.StrDate as date) as nvarchar(12)) + N''' as date) and cast(''' + cast(cast(hld1.endDate as date) as nvarchar(12))+ N''' as date)
 '

from hld1  for xml path('')),1,3,''), '&lt;', '<'), '&gt;', '>'), '&#x0D;', char(13)) +
'order by datetable.Date '


--print @sql
EXEC sys.sp_executeSQL @SQL

HLD1 是假期列表,其中每个假期都有开始和结束日期。查询本身返回定义为假期的日期列表。 (我不能只选择开始日期并将它们合并到结束日期的原因是很可能会有一个三天的假期,而中间的一天不会出现在任何一个列表中。

但是,我正在使用这个怪物来创建一个函数,并且作为函数的一部分,我希望能够执行类似“如果日期在此列表中,则执行以下操作”之类的操作。

我最初的计划是设置一个仅显示日期列表的视图;但是,这是不可能的,因为它使用变量,并且视图中不允许使用变量。

我的下一个想法是创建一个只返回列表的函数。但是,当我输入将其创建为函数的语法时,出现错误The last statement included within a function must be a return statement.

我不确定我应该从这里走哪条路。我不能只是制作一个表格并手动列出日期的原因是目前该列表仅延伸到 2016 年。此外,假期列表(开始和结束日期)可能会为不同的数据库创建/添加不同的数据库最终目标函数将被添加并使用。

如果您需要更多背景/信息,请告诉我,我很乐意提供。我只是边走边学。 :)

编辑 1:我找到了以下链接,但它似乎不适用于这种情况:Create A View With Dynamic Sql

【问题讨论】:

  • 也许您应该发布 hld1 表。表定义和几行样本数据就足够了。除此之外,您要尝试做的解释也会有所帮助。到目前为止,我只是不明白你需要完成什么。

标签: sql-server tsql dynamic-sql


【解决方案1】:

为什么不直接创建一个数字表或计数表作为持久表或视图并避免所有这些讨厌的事情。这个查询的 99% 只是生成一堆数字。

例如,这是一个执行 0 次读取并几乎立即生成 10,000 行序列号的视图。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

有你的数字部分。下一部分是创建带有假期的持久日期表,就像你正在做的那样。

这是我的好友 Dwain Camps (RIP) 关于创建日历表的精彩文章。 http://www.sqlservercentral.com/blogs/dwainsql/2014/03/30/calendar-tables-in-t-sql/

--编辑--

下面是一个包含假期开始和结束日期的表格 (#Something) 的示例。这将列出这两个日期之间的每个日期。除非我遗漏了什么,否则这应该是您正在尝试做的。

create table #Something
(
    HolidayName varchar(10)
    , StartDate date
    , EndDate date
)

insert #Something
select 'phroureo', '2016-03-01', '2016-03-05' union all
select 'Sean', '2016-07-04', '2016-07-05'

select HolidayName
    , StartDate
    , EndDate
    , DATEADD(day, t.N - 1, StartDate) as ResultDate
from #Something s
join cteTally t on t.N <= DATEDIFF(day, StartDate, EndDate) + 1
order by HolidayName

drop table #Something

【讨论】:

  • 我不确定这有什么帮助——我仍然需要使用某种动态 SQL 创建一个函数,并且数字/日期生成已经花费了不到一秒钟的时间运行。
  • 我可能只是个笨蛋,所以如果我不理解你,请告诉我。 :) 此外,“日历”表不可行的原因是 SAP(我们正在使用的软件)与 HLD1 表一起工作的方式。有一个用户界面供用户更新它。我相信我实际上是在搜索的早期阅读了那篇文章,并确定它不会满足我的需要。 :(
  • 我不太明白你为什么需要动态sql。您发布的代码非常冗长且充满重复,很难判断您的查询实际上在做什么。
  • 动态 SQL 拉取存储在数据库中的假期值,并找到假期开始日期和结束日期之间的天数,包括日期。 (例如,春假假期的开始日期可能是 3 月 1 日,结束日期是 3 月 5 日,我需要有 3/1、3/2/3 的日期列表/3 等)我不能使用日历表,因为假期已经存储在 SAP 中,并且最终用户无法从数据库后端更新手动创建的表。
  • 相反。计数表非常适合这种事情。您会发现开始和结束之间的日期差异,这就是您将用作 where 子句的日期。然后使用 DATEADD 将计数表中的值相加以获取所有日期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 2015-08-24
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 2011-06-16
相关资源
最近更新 更多