C++ MS SQL Server:在准备好的语句中访问本地临时表 问题陈述

C++ MS SQL Server:在准备好的语句中访问本地临时表 问题陈述,c++,sql-server,qt,sql-server-2008-r2,prepared-statement,C++,Sql Server,Qt,Sql Server 2008 R2,Prepared Statement,我正在尝试创建并填充一个本地临时表,该表现在运行良好,但我无法从以后的pepared查询中访问该表及其内容 该问题的一个非常简化的版本,已经重现了该问题(使用Qt5框架的C++0x): 我错过了什么?我已经很难找到创建临时表的查询来运行,直到我在下面的 在SQL Server 2005中,准备好的语句不能用于创建 临时对象[…],例如临时表。这些程序 必须直接执行 这已经相当令人困惑了,因为我使用的是SQL Server 2008r2,而为Server 2012编写的文档只提到了2005版及更旧

我正在尝试创建并填充一个本地临时表,该表现在运行良好,但我无法从以后的pepared查询中访问该表及其内容

该问题的一个非常简化的版本,已经重现了该问题(使用Qt5框架的C++0x):

我错过了什么?我已经很难找到创建临时表的查询来运行,直到我在下面的

在SQL Server 2005中,准备好的语句不能用于创建 临时对象[…],例如临时表。这些程序 必须直接执行

这已经相当令人困惑了,因为我使用的是SQL Server 2008r2,而为Server 2012编写的文档只提到了2005版及更旧的版本。尽管如此,我还是尝试在没有准备的情况下执行创建表的查询,结果成功了(参见代码示例)。然而,该引用并没有说明通过预处理语句访问临时表的任何内容

要求 由于性能原因,我不得不使用一个本地临时表:相当大的数据集将被过滤、转换并插入临时表,其中大约有10个查询将跟随并使用这个具体化的中间数据。TVP不是一个好的选择,因为它会大大降低以下查询的速度。在我的例子中,创建一个临时表的开销实际上要多付好几倍。此外,与其他解决方案相比,本地临时表更受欢迎,因为它们与其他连接隔离,并且在断开连接后将被清理,这正是我想要的

有很多原因使我不能没有准备好的陈述来阅读,所以我真的希望有人能在这方面帮助我

实际问题 如何使用准备好的查询从本地临时表(当然是从创建它的同一个连接中)读取数据


非常感谢您提出的任何想法/解决方案

将所有这些放在一个存储过程中,存储过程将创建一个以日期、时间和用户id为前缀的实际表

如此粗略

创建表someuser_190320151830

如上所述构建动态sql语句以填充表

从表中选择任何内容,以便您的应用程序可以使用它

DROP TABLE someuser_190320151830

最后一步可能是选择数据,然后删除表

除非同一个人能够在完全相同的时间运行它,否则它可能会工作。我曾使用过类似的方法,但这种方法很少使用。

具体解决方案 经过大量的测试和实验,以及我和的想法,我将一切结合到一起,最终完成工作并满足我的所有要求:

  • 我现在正在使用全局临时表,因为这些表在非准备查询和准备查询范围之间可见
  • 当客户端应用程序关闭而没有显式的
    删除时,即使它被终止或连接丢失,也会清理全局临时表
  • 我用唯一的GUID对这些表进行了后缀,这样可以避免用户和时间戳组合的冲突
最简单的例子:

QString const tableName(QString("##tmp_%1").arg(QUuid::createUuid().toString()));

// clean up, prepare empty table and fill with intermediate data
QSqlQuery query1(QString("IF EXISTS(SELECT * FROM SYSOBJECTS WHERE ID=OBJECT_ID('%1') AND XTYPE='U') DROP TABLE %1").arg(tableName), _db);
QSqlQuery query2(QString("SELECT * INTO %1 FROM mytable WHERE 1 = 0").arg(tableName), _db);
QSqlQuery query3(QString("INSERT INTO %1 SELECT mytable WHERE ...").arg(tableName), _db);

// works now! I can now select the temporary data perfectly fine from prepared statements
QSqlQuery query4(_db);
query4.prepare(QString("SELECT count(*) FROM %1 WHERE col = :boundVar").arg(tableName));
query4.bindValue(":boundVar", 1234);
query4.exec();

感谢大家的投入!我将接受s的回答,因为它会引导我这样做。

您是否可以不从应用程序中运行5个单独的查询,而是将它们全部放在存储过程中,然后从应用程序中运行存储过程?这样,它们将在数据库上的相同上下文中运行,临时表将保持不变。如果您将其更改为##tmp(这将持续更长的时间,它是一个全局临时表),其他会话可以看到它,但一旦创建它的会话结束,它将不再有会话使用它,因此它也将消失。我会按照Tab的建议去做。@Tab Alleman:这10个查询将分别从不同的表中选择巨大的数据集,只是它们使用了来自临时表的同一个会话本地预过滤数据,我如何在单个存储过程中返回这些数据?@benjamin moskovits:那么其他用户和连接不会也看到##tmp表吗?它们必须相互隔离,不能删除另一个进程的表。@ PHILPHAUBMEMEER存储过程可以返回多个结果集,使用实际表代替临时表,那么如果调用存储的PROC或执行C++中的所有查询,则不重要。该表将一直存在,直到显式删除为止。如果他使用GUID生成表名,他将不会有任何并发问题。谢谢你的想法。然而,我并不喜欢这些表必须手动清理的事实。如果连接丢失或程序在执行过程中终止,表将被卡住,数据库中会挤满孤立的表。更重要的是,临时表的引入正是出于这个原因,所以我真的很想使用这个功能。接受你的回答-谢谢你的帮助。请参阅我现在实施的具体解决方案的答案。我遇到了类似的问题。我非常愿意使用你的解决方案。然而,对于如何使用全局临时表来解决这个问题,我仍然不清楚。i、 例如,即使您用唯一的GUID对这些表进行后缀,它对其他连接和用户是否仍然可见?其他用户就不能在上面运行查询了吗?(如果是本地临时表,情况就不会如此)。如果我遗漏了什么,请纠正我?@Mohammed Raqeeb:是的,表对于其他连接和用户是可见的,但这不是问题,因为GUID不会冲突,因此任何用户的其他应用程序实例都不会使用/查询表。此外,其中没有机密值,只有一组经过筛选的表,该表已对数据库的所有用户可见。
QString const tableName(QString("##tmp_%1").arg(QUuid::createUuid().toString()));

// clean up, prepare empty table and fill with intermediate data
QSqlQuery query1(QString("IF EXISTS(SELECT * FROM SYSOBJECTS WHERE ID=OBJECT_ID('%1') AND XTYPE='U') DROP TABLE %1").arg(tableName), _db);
QSqlQuery query2(QString("SELECT * INTO %1 FROM mytable WHERE 1 = 0").arg(tableName), _db);
QSqlQuery query3(QString("INSERT INTO %1 SELECT mytable WHERE ...").arg(tableName), _db);

// works now! I can now select the temporary data perfectly fine from prepared statements
QSqlQuery query4(_db);
query4.prepare(QString("SELECT count(*) FROM %1 WHERE col = :boundVar").arg(tableName));
query4.bindValue(":boundVar", 1234);
query4.exec();