2

原始问题: 我正在处理一个数据库,每个月都会生成一个新表,并将YYYY_MM附加到新的表名。我需要编写一个查询,查看当前月份的表格。抛开日期函数,我发现我无法构建表名!如何在SQL查询的FROM区域中使用动态表名称?

实施例表名称将是DOCUMENTS_2011_10

我试图用一个基本的脚本是这样,但它没有对语法问题:

SELECT * FROM ('DOCUMENTS_'+'2011_10') 

有什么建议?

附加信息:正在我们的企业门户应用程序(甲骨文的WebCenter交互)产生 表。重新设计这个应用程序以改变它的数据处理方式是不可能的。

我一直在问,提取出从每月生成这些表主要数据报告。

我的办法将是创建一个SQL报告服务的订阅,将在Excel格式,每月通过电子邮件发送的数据。
我需要帮助与此查询到其插入报告服务,所以我不会有每个月与查询涉足更改表名。

由于报告服务每个月将触发并生成报告,数据的归档,或任何类型的特设能力是不需要的。

使用动态SQL我能够设置表名,遗憾的是,当我尝试添加自己的查询其余它抱怨一个字符的限制问题。任何想法如何解决这个问题?

这让我正确的表:

Declare @tblName Varchar(400) 
Declare @SQL Varchar(500) 

Set @tblName = 
'analyticsdbuser.ASFACT_DOCUMENTVIEWS_' 
+ CONVERT(VARCHAR,DATEPART(yyyy,GETDATE())) 
+ '_' 
+ CONVERT(VARCHAR, RIGHT('0' + RTRIM(MONTH(GETDATE())-1), 2)); 

SET @SQL = 'SELECT * FROM ' + @Tblname; 
Exec(@SQL) 

这是其他查询,所有需要得到执行,但不适合进入@SQL:

SELECT t2.ID, 
     t2.USERID, 
     t3.NAME, 
     t2.DOCUMENTID, 
     t1.NAME AS DOC_NAME, 
     t4.PROPERTYID, 
     t5.NAME AS PROP_NAME, 
     t4.VALUE 

FROM  ASFACT_DOCUMENTVIEWS_2011_10 AS t2 INNER JOIN 
     ASDIM_USERS AS t3 ON t3.USERID = t2.USERID INNER JOIN 
     ASDIM_USERPROPERTYVALUES AS t4 ON t4.USERID = t2.USERID INNER JOIN 
     ASDIM_KDDOCUMENTS AS t1 ON t1.ID = t2.DOCUMENTID INNER JOIN 
     ASDIM_USERPROPERTIES AS t5 ON t4.PROPERTYID = t5.PROPERTYID 

WHERE (t2.DOCUMENTID IN ('33449', '36241', '36566')) AND 
     (t4.PROPERTYID IN (26, 156, 157, 158, 159, 325, 160, 162)) 

ORDER BY t2.DOCUMENTID, 
     t3.NAME; 

PARTITIONING问题 我不熟悉一些人提到的分区概念,并且会在这个时候查看它。

万一它很重要,每个这些月表只有大约20K行和1.5MB(我们不是一个大公司,这个软件是为在这些月表中获得数百万行的公司设计的)

+0

您是否考虑过使用SQL Server的分区功能来水平分解表?如果完全可以避免动态命名的表,它将为您节省很多动态SQL的麻烦。 – JohnFx

+0

是的,应该使用分区,如果可用的话。否则...并不完全消除对动态SQL的需求,但我们在这里所做的一件事是为所需的表创建一个临时_alias_(动态),然后在我们的SQL中使用别名的(常数)名称。如果您使其能够汇总来自多个来源(例如三个月)的数据,这也具有这样的效果。 –

+0

如果动态SQL不适合变量,并且没有使用分区,那么可以使变量的内容更短。只需抓住一个表并将结果放入临时表中即可。然后用临时表而不是动态命名的表再次执行主查询,而不需要更长查询所需的动态SQL。 –

回答

7

在SQL Server中,对象和列名不能动态化。

你不得不使用动态SQL来构建它,说与sp_executesql的

... 
SET @SQL = 'DOCUMENTS_'+'2011_10'; 
EXEC sp_executesql @sql ... 

话说,在嵌入的对象名称类似这样的信息通常是不好的做法。如果你想在一个查询中使用3个月的数据会发生什么?

+0

另外,要小心,因为如果你在存储过程中这样做,它将以PROC的所有者的权限执行,而不是当前用户。 – JohnFx

+0

@JohnFx:是的,我不喜欢动态SQL – gbn

+0

的原因之一......并且有很多原因可以避免它。因此,OP有理由重新考虑这种动态命名表。 – JohnFx

2

不知道更多 - 有选项

  1. 编写动态SQL一个numebr:http://www.tek-tips.com/faqs.cfm?fid=3132

    Set @SQL = 'SELECT * From #TempTable Where EmpID in (' + @INList +')' 
    Exec(@SQL) 
    

    可能是你在找什么,但

  2. 你有conisdered分区的意见,只有从视图访问?它可以将事物保存在各自的表格中,然而 - 提供对数据的访问,就像ti在一个地方一样。

+1

您的第一个构造与动态表名无关并且是SQL注入风险 – gbn

+0

+1分区视图是一个好建议 – Andomar

+0

感谢分区建议 - 我将调查此问题,因为我采取的方法看起来很笨重。 – user1050584

相关问题