【问题标题】:PL/pgSQL perform vs executePL/pgSQL 执行与执行
【发布时间】:2017-03-21 07:43:43
【问题描述】:

在 PL/pgSQL 上执行和执行有什么区别?

来自手册:

有时对表达式或 SELECT 查询求值但丢弃结果很有用,例如在调用具有副作用但没有有用结果值的函数时。要在 PL/pgSQL 中执行此操作,请使用 PERFORM 语句。

但是,当我尝试这样的事情时:

perform 'create table foo as (select 1)';

什么都没有发生。虽然这个查询应该有副作用(建表),结果可以丢弃。

我认为我做对了 1 件事:为了运行我可以使用 perform 的功能:

perform pg_temp.addInheritance(foo);

【问题讨论】:

  • perform 替换 select。是选择忽略返回,你不能select 'create table foo as (select 1)';
  • 也就是说,它不能对数据库做任何改变?
  • 可以,select 可以。不多不少。例如select pg_create_restore_point('change to db'); 或 select 1 from dblink_exec('local', 'create table...') as (i int)` 左右

标签: postgresql plpgsql


【解决方案1】:

PERFORM 是用于调用 void 函数的 plpgsql 命令。 PLpgSQL 对无用的SELECT 语句很小心——不允许使用没有INTO 子句的SELECT。但有时你需要调用一个函数而你不需要存储结果(或者函数没有结果)。使用SELECT 语句调用SQL 中的函数。但这在 PLpgSQL 中是不可能的——因此引入了命令PERFORM

CREATE OR REPLACE FUNCTION foo()
RETURNS void AS $$
BEGIN
  RAISE NOTICE 'Hello from void function';
END;
$$ LANGUAGE plpgsql;

-- direct call from SQL
SELECT foo();

-- in PLpgSQL
DO $$
BEGIN
  SELECT foo(); -- is not allowed
  PERFORM foo(); -- is ok
END;
$$;

PERFORM 语句执行一个参数并忘记了结果。

你的例子perform 'create table foo as (select 1)';

SELECT 'create table foo as (select 1)' 相同。它返回一个字符串“create table foo as (select 1)”并且这个字符串被丢弃。

EXECUTE 语句计算表达式以获取字符串。下一步将执行此字符串。

所以EXECUTE 'create table ' || some_var || '(a int)'; 有两个步骤

  1. 评估表达式'create table ' || some_var || '(a int)'
  2. 如果some_var例如是mytab,则执行命令create table mytab(a int)

PERFORM 语句用于函数调用,当函数不用于赋值语句时。 EXECUTE 用于评估动态 SQL - 当一种形式的 SQL 命令在运行时已知时。

【讨论】:

    【解决方案2】:

    docs you quote 中的下一行:

    这会执行查询并丢弃结果。 写出同样的查询 以编写 SQL SELECT 命令的方式,但替换初始 关键字 SELECT 和 PERFORM。

    强调我的

    execute 依次执行动态查询(上面的文档相同)

    【讨论】:

      【解决方案3】:

      我最近遇到一个案例,我需要为 DEFERRED 设置特定的约束,并发现了一些有趣的东西。

       - EXECUTE 'SET CONSTRAINTS fk_a DEFERRED';
       - PERFORM 'SET CONSTRAINTS fk_a DEFERRED';
      

      EXECUTEPERFORM 都执行了语句而没有错误,但只有 EXECUTE 保留了其余代码的操作。 不知何故,PERFORM 似乎在它自己的事务 "bubble" 中运行。

      就我而言,我有两个表 a 和 b 以及一个 FK(实际情况要复杂得多)。需要从父/子顺序中插入数据,为此我们需要约束DEFERRED。 使用 PERFORM 我们有外键违规,而 EXECUTE 我们没有。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-27
        • 1970-01-01
        • 1970-01-01
        • 2021-02-01
        相关资源
        最近更新 更多