postgresql 我可以试运行/沙盒SQL命令吗?

ocebsuys  于 2023-04-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(142)

我正在尝试构建一个小的Rails应用程序,以游戏的形式向初学者教授SQL。它的一部分是一个命令行,用户试图用SQL解决问题。在后端,我想对一个测试数据库运行他们的SQL命令,并检查结果,看看他们的命令是否正确。
我目前的想法是为课程的每个阶段创建sqlite数据库,然后在每个用户到达该阶段时为他们创建该数据库的副本。
我认为这是可行的,但我担心效率。
我的问题是是否有一种有效的方法让用户运行SQL命令(包括dropalter等)。),获得结果,但实际上并不对数据库本身进行任何更改,本质上是任意SQL命令的干运行。我熟悉sqlite和postgres,但对其他数据库持开放态度。

lrl1mhuk

lrl1mhuk1#

在Postgres中,你可以对transactions做很多事情,这些事务在最后被回滚

BEGIN;

UPDATE foo ...:
INSERT bar ...;
SELECT baz FROM ...;
CREATE TABLE abc...;   -- even works for DDL statements
DROP   TABLE def...;
ALTER  TABLE ghi ...:

ROLLBACK;   -- !

不要做COMMIT
阅读有关BEGINROLLBACK的手册。
但是要注意,有些事情是无法回滚的。例如,序列不会回滚。或者一些特殊的命令,比如dblink调用。
并且某些命令不能在与其他命令的事务中运行。例如CREATE DATABASEVACUUM
此外,并发加载可能会有副作用,如死锁。不过,不太可能。您可以将transaction isolation level设置为您的要求,以排除任何副作用(以性能为代价)。
我不会对敏感数据这样做。意外犯罪的风险太大了。让用户执行任意代码是一种几乎无法控制的风险。但对于一个训练环境来说,这应该足够好了。
模板数据库备份。如果出了问题,这是恢复基本状态的最快方法。示例(看最后一章):

  • 截断Postgres数据库中的所有表

这也可以用作暴力破解替代:为每个学员提供一个全新的数据库。

whlutmcx

whlutmcx2#

虽然您可以在事务中运行它们的代码,然后在回滚之前尝试检查同一事务中的结果,但这会有一些挑战。
首先,如果他们的代码中有任何错误,事务将中止。除了“它失败了,这是错误消息”之外,你什么也说不出来。特别是,您将无法在错误之前检查部分结果。
其次,如果您在单个数据库中进行并行运行,那么锁定会对您造成影响。每个会话将获得锁,通常是元组或整个关系上的排他锁。其他会话将阻止等待锁。这意味着您必须连续地运行测试。这在你的环境中可能不是一个问题,但值得考虑。
第三,正如Erwin所指出的,您必须使检查代码对序列值之类的东西不敏感,因为它们在回滚时不会重置。
基于这些原因,我强烈建议:

CREATE DATABASE course_username_lesson TEMPLATE course_lesson OWNER username;

...或者省略模板数据库的使用,让Rails应用程序为每个用户使用迁移设置一个空白数据库。这可能更简单,因为这意味着您不必维护模板DB。
一个PostgreSQL服务器可以很好地处理成百上千的数据库,至少如果它不需要在高峰生产负载下运行的话。
您可能需要查看http://sqlfiddle.com/和许多其他现有的基于Web的SQL编辑器/培训工具,其中许多都是开源的。

相关问题