Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PL/PGSQL中循环通过游标而不锁定表_Sql_Postgresql_Transactions_Plpgsql_Postgresql 9.5 - Fatal编程技术网

在PL/PGSQL中循环通过游标而不锁定表

在PL/PGSQL中循环通过游标而不锁定表,sql,postgresql,transactions,plpgsql,postgresql-9.5,Sql,Postgresql,Transactions,Plpgsql,Postgresql 9.5,我有一个简单的PL/PGSQL块Postgres 9.5,它循环表中的记录并有条件地更新一些记录 下面是一个简化的示例: 做$$ 声明 -定义一个游标来循环记录 我的\u cool\u光标用于 选择 u、 id作为用户\u id, u、 名称作为用户名, u、 以用户身份发送电子邮件 来自用户u ; 开始 在my_cool_光标循环中记录 -简化示例: -如果用户的名字是“Anjali”,请将电子邮件设置为空 如果record.user_name='Anjali',则 开始 更新用户设置emai

我有一个简单的PL/PGSQL块Postgres 9.5,它循环表中的记录并有条件地更新一些记录

下面是一个简化的示例:

做$$ 声明 -定义一个游标来循环记录 我的\u cool\u光标用于 选择 u、 id作为用户\u id, u、 名称作为用户名, u、 以用户身份发送电子邮件 来自用户u ; 开始 在my_cool_光标循环中记录 -简化示例: -如果用户的名字是“Anjali”,请将电子邮件设置为空 如果record.user_name='Anjali',则 开始 更新用户设置email=NULL,其中id=record.user\u id; 终止 如果结束; 端环; 终止 $$语言plpgsql; 我想通过我的应用程序,通过控制台等,直接对我的数据库执行此块。。。。我不想创建函数或存储过程来执行此操作

问题 问题是游标和循环在我的users表上创建了一个表级锁,因为外部BEGIN…END之间的所有内容都在事务中运行。这将阻止针对它的任何其他未决查询。如果用户足够大,则会将其锁定几秒钟甚至几分钟

我试过的 我尝试在每次更新后提交,以便它定期清除事务和锁。我惊讶地看到以下错误消息:

ERROR:  cannot begin/end transactions in PL/pgSQL
HINT:  Use a BEGIN block with an EXCEPTION clause instead.
我不太清楚这是怎么做到的。是不是要求我提出一个例外来强制提交?我试着阅读,但它只提到回滚,所以我看不到任何提交的方法

如何在上面的循环中定期提交事务? 更一般地说,我的方法是正确的吗?有没有更好的方法在不锁定表的情况下循环记录? 1. 您不能在PostgreSQL或命令中提交所有plpgsql或任何其他PL。您报告的错误消息与Postgres 9.5有关:

A可以在11级或更高级别的研究生中做到这一点。见:

在旧版本中实现自治事务的变通方法有限:

但在本案例中,您不需要任何这些

2. 改用简单的更新:

仅锁定实际更新了角点大小写异常的行。由于这比光标在整个表上移动快得多,所以锁也非常简短

添加的和电子邮件与NULL不同,避免了空更新。相关的:


在plpgsql函数中,显式游标很少有用。

如果要避免长时间锁定行,还可以使用HOLD定义游标,例如使用SQL语句

这样的游标可以跨事务边界使用,因此您可以在一定数量的更新之后提交。您付出的代价是必须在数据库服务器上具体化游标


由于不能在函数中使用事务语句,因此必须在应用程序代码中使用过程或提交。

光标不会阻止其他只读查询。但是我不认为有必要用一个缓慢而低效的光标来开始感谢。我给出的UPDATE语句只是一个简化的示例。我真正的逻辑要复杂得多,所以我不认为我可以在一次更新中解决这个问题。@user2490003:你仍然可以。也许值得再问一个关于细节的问题。。。
ERROR:  cannot begin/end transactions in PL/pgSQL
UPDATE users
SET    email = NULL
WHERE  user_name = 'Anjali'
AND    email IS DISTINCT FROM NULL;  -- optional improvement