使用 python 执行 PL/PGSQL 块而不将它们存储到数据库中
Posted
技术标签:
【中文标题】使用 python 执行 PL/PGSQL 块而不将它们存储到数据库中【英文标题】:executing PL/PGSQL blocks using python without storing them into database 【发布时间】:2013-01-12 12:12:19 【问题描述】:我正在使用 python 构建 Django 应用程序,该应用程序预计会接收大量数据,我已经研究了一些可以提高性能的 PL/PGSQL 程序。这些过程存储在文件中,我不想在数据库上创建它们。
我只想能够使用 postgresql_psycopg2 执行它们,另一个棘手的部分是我希望能够在执行之前更改文件中的一些参数,但不确定如何处理它。
这是我的 Python 代码
pg_script = os.path.join(getattr(settings, 'BASE_DIR'),'myapp/apps/rating/sql/rating_create_article_rating.sql')
cursor = connection.cursor()
cursor.execute("run script %s" % pg_script)
这里是 rating_create_article_rating.sql
DECLARE
article_rec publication_article%ROWTYPE;
user_rec auth_user%ROWTYPE;
up integer := 1;
down integer := -1;
l_counter integer := 0; -- local counter
cnt integer;
p_content_type_id integer;
BEGIN
LOOP
-- RANDOM ARTICLE
SELECT *
INTO article_rec
FROM publication_article
order by random()
LIMIT 1;
-- RANDOM USER
SELECT *
INTO user_rec
FROM auth_user
order by random()
LIMIT 1;
BEGIN
INSERT INTO rating_rate (rated_by_id, rated_at, content_type_id, object_id, rate, language)
VALUES (user_rec.id, now(), p_content_type_id, article_rec.id, 1, 'en');
l_counter := l_counter+1;
EXCEPTION
WHEN unique_violation THEN
END;
EXIT WHEN l_counter>cnt;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
当我将上面的代码作为存储函数执行时,上面的代码有效,否则运行脚本不起作用,我收到以下错误
ERROR: syntax error at or near "run" at character 1
STATEMENT: run script /Users/mo/Projects/pythonic/myapp-env/myapp/myapp/apps/rating/sql/rating_create_article_rating.sql
我还想知道是否有办法将参数传递给文件并从 pl/pgsql 处理它?
非常感谢
【问题讨论】:
您可以使用匿名函数。DO $$ -- Code $$;
postgresql.org/docs/current/static/sql-do.html
在使用匿名函数时,是引用脚本位置还是读取脚本内容并将其转储到光标中?
不知道你为什么不把过程放在数据库中并调用它。我想应该会更快。
【参考方案1】:
首先,我更喜欢将这些东西放在函数中。一个重要的原因是,这有助于分离 sql 和应用程序代码,使其更易于阅读和查找所需内容。函数还可以进行一些优化。
如果这还不够,请使用 DO 块。 DO 块有许多重要的限制。例如,它们不能返回结果。这意味着,如果您想返回有关插入或类似内容的有用信息,则不能这样做。
DO
创建一个没有返回类型的匿名函数。您可以将您的函数体包含在 DO LANGUAGE PLPGSQL $$ .. $$;
块中,它会立即运行。
【讨论】:
以上是关于使用 python 执行 PL/PGSQL 块而不将它们存储到数据库中的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PostgreSQL、PL/pgSQL 上执行匿名代码块切换 CASE 语句?
PL/pgSQL 函数 - 遍历特定列并在循环中执行第二个查询