我正在某个日期时间段(即05/01/2012至05/31/2012)上运行数据库的复杂查询列表。然后我需要在06/01/2012到06/30/2012运行相同的查询。然后将结果加入报告目的。
在查询中,我使用了几个表变量来保存临时数据。由于数据库很大,表变量大小也很大。有没有办法可以重用这些表变量?
DROP,Truncate不起作用。我是否必须删除@table中的所有数据?如果是这样,它会慢吗?我是否必须为@table进行批量删除,因为它有大量数据?
顺便说一句,由于系统的设计方式,我必须将所有查询放在一个SP文件中,无法调用函数或其他SP。感谢
=============================
查询中没有循环。它的工作原理如下:
选择.....选择.....更新.....加入......
对日期05/01/2012至05/31/2012进行一组查询。然后需要在06/01/2012到06/30/2012的同一组查询。
在查询中,内部有很多逻辑,因此我们无法将这两个组合成一组查询。由于系统设计,我们不能为查询调用函数或SP。必须按顺序进行第一组查询,然后进行第二组查询。
问题是数据太多,@ table太大了。如果我们可以重用@table,它将解决问题。
感谢
===============================
是的,现在,相同的代码,对于2个不同的日期时间间隔重复两次。但是,在代码中,它有一些逻辑内部,不同的进程基于datetime之间的差异。对不起,我无法发布实际代码。但是,该过程就像一个具有不同日期时间作为参数的SP。
但是,在这种情况下我不能使用SP /函数,因此必须对相同的代码进行两次硬编码。理想情况下,每次重复代码时都需要使用不同的@table(现在,我需要重复3次),但由于数据大小,如果我重复3次@table太大(每个需要多个@table)做逻辑部分)。
也许我最好使用临时表?所以我可以在开始新的'重复'时放弃它?
感谢
答案 0 :(得分:13)
表变量未记录在当前数据库中,并且不受事务约束。为什么你认为截断或删除比删除更快?你试过这个吗?
DECLARE @f TABLE(id INT);
INSERT @f SELECT 1;
BEGIN TRANSACTION;
DELETE @f WHERE id = 1;
ROLLBACK TRANSACTION;
SELECT id FROM @f;
没有结果。现在,如果删除已完全记录在当前数据库中(这使得DELETE
比普通用户表的TRUNCATE
慢),您可能希望DELETE
已回滚,SELECT
应该返回数据。但不,删除不是交易的一部分。然后,您可以在逻辑上得出结论,DELETE
和TRUNCATE
非常相似,如果不相同则允许后者。
如果必须使用表变量,只需使用删除即可。如果你觉得它很慢,可能不是因为删除,可能是因为你在循环中重用表变量,而不是使用基于集合的操作。但是当然,如果你使用两个不同的@table变量而不是重复使用单个表变量并在两者之间发出删除,那么你比我们任何人都更好地测试你的代码会慢多少。但我仍然认为你的整个过程需要重新调查,因为在很多层面上我觉得它不是最佳的。
答案 1 :(得分:1)
当然,但你真正想要的不是表参数,而是你需要一个临时表。
CREATE TABLE #my_temp_table (column1 int, column2 varchar(max), ...)
INSERT INTO #my_temp_table (column1, column2) VALUES (...)
-- Use the temporary table here
DELETE FROM #my_temp_table
INSERT INTO #my_temp_table (column1, column2) VALUES (...)
-- Use the temporary table again
DROP TABLE #my_temp_table
编辑:提交者可能会说“我不能使用表变量,因为它传递给我的存储过程,标志为READONLY”。在这种情况下,他可能会因为将其转换为临时表而获得一些里程数。
作为旁注,虽然SQL Server的文档声称并非如此,但我已经看到临时表比表变量更好的实例。我相信这是因为我把我的TEMPDB放在一个单独的磁盘上,它有很多可用的IO容量。
但请记住,临时表存在命名问题 - 如果存储过程尝试为临时表创建命名冲突,则可以锁定存储过程。表变量不会遇到这个问题。