PL/pgSQL匿名代码块

1ac*_*ac0 5 postgresql plpgsql

在PostgreSQL 9.0中,我有这个PLPGSQL匿名代码块:

DO $$
    DECLARE
        bigobject integer;
    BEGIN
        SELECT lo_creat(-1) INTO bigobject;
        ALTER LARGE OBJECT bigobject OWNER TO postgres;
        INSERT INTO files (id, "mountPoint", data, comment) VALUES (15, '/images/image.png', bigobject, 'image data');
        SET search_path = pg_catalog;
        SELECT pg_catalog.lo_open(bigobject, 131072);
        SELECT pg_catalog.lowrite(0, '\\x000001000100101010000000000028010000160000002800000010000000200000000100040');
        SELECT pg_catalog.lo_close(0);
        REVOKE ALL ON LARGE OBJECT bigobject FROM PUBLIC;
        REVOKE ALL ON LARGE OBJECT bigobject FROM postgres;
        GRANT ALL ON LARGE OBJECT bigobject TO postgres;
        GRANT ALL ON LARGE OBJECT bigobject TO "com.ektyn.eshops.myuser";
    END
$$;
Run Code Online (Sandbox Code Playgroud)

但它失败了:

ERROR:  syntax error at or near "bigobject"
LINE 6:   ALTER LARGE OBJECT bigobject OWNER TO postgres;
                             ^

********** Error **********

ERROR: syntax error at or near "bigobject"
SQL state: 42601
Character: 103
Run Code Online (Sandbox Code Playgroud)

而我在代码中找不到错误.

kli*_*lin 6

必须有一个OID恒ALTER LARGE OBJECT oid ....试试这个解决方法:

DO $$
    DECLARE
        bigobject integer;
    BEGIN
        SELECT lo_creat(-1) INTO bigobject;
        EXECUTE 'ALTER LARGE OBJECT ' || bigobject::text || ' OWNER TO postgres';
        ...
Run Code Online (Sandbox Code Playgroud)

当然,同样适用于GRANT和REVOKE.


Erw*_*ter 5

除了@klin已经清理的内容之外,如果没有SELECTplpgsql代码中的目标,则无法使用.PERFORM在那些电话中替换它.

旁白:使用"com.ektyn.eshops.myuser"角色名称是一个可怕的想法.使用不必双引号的合法小写标识符.


Cra*_*ger 5

这是 PostgreSQL 在内部有两种完全不同类型的 SQL 语句 - 可计划( SELECT, INSERT, UPDATE, 和DELETE) 和不可计划(其他所有) 语句这一事实的产物

只有可规划语句支持查询参数。

PL/pgSQLbigobject使用查询参数将变量替换为语句,例如您的。

因为不可规划语句不支持它们,所以不执行替换。所以 PL/pgSQL 尝试按字面意思执行语句,就好像你输入了:

ALTER LARGE OBJECT bigobject OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)

直接按psql提示。它不会将此检测为错误。

要解决此问题,请使用EXECUTE ... FORMAT,例如

EXECUTE format('ALTER LARGE OBJECT %s OWNER TO postgres', bigobject);
Run Code Online (Sandbox Code Playgroud)

请参阅有关COPY.