【发布时间】:2015-05-22 22:07:33
【问题描述】:
问题陈述
我正在尝试创建并填充一个本地临时表,它现在运行良好,但之后我无法从 pepared 查询中访问该表及其内容。
这个问题的一个非常简化的版本,已经重现了这个问题(C++0x with Qt5 framework):
// fyi: this constructor overload already executes the given query string
QSqlQuery query1("IF EXISTS(SELECT * FROM SYSOBJECTS WHERE ID=OBJECT_ID('#tmp') AND XTYPE='U') DROP TABLE #tmp", _db);
QSqlQuery query2("SELECT * INTO #tmp FROM mytable WHERE 1 = 0", _db);
// so far, so good: the table gets dropped if it was already existing and gets recreated with the schema of 'mytable'; it is empty due to the '1 = 0'
// this works: some code for inserting data
QSqlQuery query3("INSERT INTO #tmp SELECT mytable WHERE ...", _db);
// this also works: i can select some data
QSqlQuery query4("SELECT count(*) FROM #tmp WHERE col = 1234", _db);
Q_ASSERT(query4.hasNext());
// fails at exec() with error: "unkown object name '#tmp'"
QSqlQuery query5(_db);
query5.prepare("SELECT count(*) FROM #tmp WHERE col = :boundVar");
query5.bindValue(":boundVar", 1234);
query5.exec();
我在这里想念什么?我已经很难让创建临时表的查询运行起来,直到我在SQL Server documentation 中读到这个:
在 SQL Server 2005 中,准备好的语句不能用于创建 临时对象 [...],例如临时表。这些程序 必须直接执行。
这已经很令人困惑了,因为我使用的是 SQL Server 2008r2 - 而为 Server 2012 编写的文档只提到了 2005 和更早的版本。尽管如此,我尝试在不准备的情况下执行创建表的查询并且它工作(参见代码示例)。然而,这句话并没有说明通过准备好的语句访问临时表。
要求
由于性能原因,我必须使用本地临时表:相当大的数据集将被过滤和转换并插入到临时表中,大约 10 个查询将跟随并使用这些物化的中间数据。 TVP 不是一个好的选择,因为它会大大减慢以下查询的速度。在我的情况下,创建临时表的开销确实是好几倍。此外,本地临时表将比其他解决方案更受欢迎,因为它们与其他连接隔离,并且在断开连接后会被清理,这正是我想要的。
我不能没有准备好的从表格中阅读的语句有很多原因,所以我真的希望有人可以帮助我。
实际问题
如何使用准备好的查询从本地临时表(当然是在创建它的同一连接中)读取数据?
非常感谢任何想法/解决方案!
【问题讨论】:
-
不是从您的应用程序运行 5 个单独的查询,您可以将它们全部放在一个存储过程中,然后从应用程序运行存储过程吗?这样一来,它们都将在数据库上的相同上下文中运行,并且临时表将持续存在。
-
您必须在同一个 SQL Server 会话中,而不是客户端会话中。如果将其更改为##tmp(这将持续更长时间-它是一个全局临时表),其他会话可以看到它,但是一旦创建它的会话结束,它将没有更多会话使用它,因此它也会消失。我会按照 Tab 的建议去做。
-
@Tab Alleman:这 10 个查询将分别从不同的表中选择大量数据集,只是它们使用临时表中相同的会话本地预过滤数据,我将如何在单个存储过程?
-
@benjamin moskovits:那么其他用户和连接不会也看到##tmp 表吗?它们必须相互隔离,不能删除另一个进程的表。
-
@PhilipDaubmeier 存储过程可以返回多个结果集
标签: c++ sql-server qt sql-server-2008-r2 prepared-statement