【问题标题】:execute sql inside plpgsql function在plpgsql函数中执行sql
【发布时间】:2014-05-16 12:05:25
【问题描述】:

使用 postgreSQL 9.1.9,我有一些这样的 SQL 请求:

 INSERT INTO "my_table" VALUES(10,'James','California');

下面是原始名称查找表的简化表...

  names

  name_id      name
  ---          -----
  3            James

但实际上我不必输入(进入“my_table”)SQL请求提供的文本值(人名,州名),而是其对应的ID位于另一个表中(例如:名称表)

所以我正在考虑创建一个触发器,调用一个应该执行选择 SQL 请求并返回要插入的修改行的函数。

这可能吗?

CREATE FUNCTION insert_by_ID() RETURNS TRIGGER AS '

        BEGIN
            --Can we execute this query, store the result in a variable to be added
              to the NEW record?

            SELECT name_id from names where name=NEW.name;

                           --this request would be...
                           --SELECT name_id from names where name='James'     
          RETURN NEW;
        END;
        ' LANGUAGE plpgsql;

CREATE TRIGGER insert_info_ID
        BEFORE INSERT ON my_table
        FOR EACH ROW
        EXECUTE PROCEDURE insert_by_ID();

【问题讨论】:

  • 当然可以,但可能是多余的。用 my_tablenames 定义完成您的问题。
  • 在 psql 中运行 \d names 并发布输出。另外,总是你的 Postgres 版本。并请澄清模糊的解释。
  • 你的问题还不清楚。我猜你可能需要一个可更新的视图。请阅读这篇文章:vibhorkumar.wordpress.com/2011/10/28/instead-of-trigger
  • 我们是在处理可以总是在表names 中找到的名称,还是如果没有找到,您想插入名称并继续新创建的name_id ?如果是这样,我们是否正在处理繁重的并发写入负载?

标签: sql postgresql plpgsql


【解决方案1】:

我有根据的猜测是您想要解决“SELECT or INSERT if not exist”问题。

我建议你创建一个这样的 plpgsql 函数:

CREATE OR REPLACE FUNCTION f_name_id(_name text, OUT _name_id int) AS
$func$
BEGIN

LOOP
   BEGIN

   SELECT name_id FROM names WHERE name = _name FOR SHARE   -- lock!
   INTO  _name_id;

   IF NOT FOUND THEN
      INSERT INTO names (name) VALUES (_name) RETURNING name_id
      INTO  _name_id;
   END IF;

   EXCEPTION WHEN UNIQUE_VIOLATION THEN      -- inserted concurrently!
      RAISE NOTICE 'It actually happened!';  -- hardly ever happens
   END;

   EXIT WHEN _name_id IS NOT NULL;           -- else try again
END LOOP;

END
$func$ LANGUAGE plpgsql;

这是一个简单的版本(更多解释和链接在那里):
Is SELECT or INSERT in a function prone to race conditions?

插入

那么您的INSERT 语句可能如下所示:

INSERT INTO my_table(my_table_id, name_id, state) -- always with column list
VALUES (10, f_name_id('James'), 'California');

【讨论】:

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