Postgresql

創建約束以停止對錶的大規模更新

  • November 14, 2013

我想創建一個約束,以便如果表中超過 5 行正在使用UPDATE語句更新,它應該警告使用者/阻止查詢。

實現此目的的一種方法是使用觸發器並行更新臨時表(僅在同一會話中可見)。

使用 創建臨時表ON COMMIT DROP,以便它在事務期間存在。這樣,同一事務期間的所有更新都將計入最大值。

展示表:

CREATE TABLE foo(id serial, txt text)

觸發功能:

CREATE OR REPLACE FUNCTION trg_foo_maxup()
 RETURNS trigger AS
$func$
DECLARE
 _ct int;
BEGIN

IF EXISTS (
  SELECT 1 FROM pg_catalog.pg_class
  WHERE  relname = 'foo_maxup'
  AND    relnamespace = pg_my_temp_schema()
  AND    relkind = 'r'
  ) THEN

  UPDATE foo_maxup SET ct = ct + 1
  RETURNING ct INTO _ct;

  IF _ct > 5 THEN           -- your maximum here
     RAISE EXCEPTION 'Cannot update more than 5 rows in one transaction!';
  END IF;

ELSE
  CREATE TEMP TABLE foo_maxup ON COMMIT DROP AS
  SELECT 1 AS ct;
END IF;

RETURN NEW;

END
$func$
 LANGUAGE plpgsql VOLATILE SET search_path = pg_temp;

扳機:

CREATE TRIGGER maxup
BEFORE UPDATE ON foo
FOR EACH ROW
EXECUTE PROCEDURE trg_foo_maxup();

如果您想要整個會話的最大值,只需省略ON COMMIT DROP.

我添加SET search_path = pg_temp到函式定義中以防止search_path. 此觸發器僅在其search_path. 這就是為什麼pg_catalog.pg_class必須是表限定的。

-> SQLfiddle 展示

引用自:https://dba.stackexchange.com/questions/53145