這是一個有點簡單化,但假設正在運行9.2
或更高版本,這是一個如何檢查單功能許可執行INSERT的例子:
CREATE TABLE my_table (col1 text, col2 integer, col3 timestamp);
CREATE FUNCTION my_table_insert_function(col1 text, col2 integer) RETURNS integer AS $$
BEGIN
INSERT INTO my_table VALUES (col1, col2, current_timestamp);
RETURN 1;
END $$ LANGUAGE plpgsql;
CREATE FUNCTION my_table_insert_trigger_function() RETURNS trigger AS $$
DECLARE
stack text;
fn integer;
BEGIN
RAISE EXCEPTION 'secured';
EXCEPTION WHEN OTHERS THEN
BEGIN
GET STACKED DIAGNOSTICS stack = PG_EXCEPTION_CONTEXT;
fn := position('my_table_insert_function' in stack);
IF (fn <= 0) THEN
RAISE EXCEPTION 'Expecting insert from my_table_insert_function'
USING HINT = 'Use function to insert data';
END IF;
RETURN new;
END;
END $$ LANGUAGE plpgsql;
CREATE TRIGGER my_table_insert_trigger BEFORE INSERT ON my_table
FOR EACH ROW EXECUTE PROCEDURE my_table_insert_trigger_function();
和使用的一個簡單的例子:
INSERT INTO my_table VALUES ('test one', 1, current_timestamp); -- FAILS
SELECT my_table_insert_function('test one', 1); -- SUCCEEDS
你要偷看進棧更詳細,如果你想你的代碼更加可靠,安全等多項功能的檢查是可能的,當然,但涉及更多的工作。將堆棧分成多行並解析它可能會相當複雜,所以如果事情變得更復雜,您可能需要一些幫助函數。
這只是一個概念的證明,但它做它聲稱的東西。如果使用異常處理和堆棧檢查,我希望這段代碼相當慢,所以不要在應用程序的性能關鍵部分使用它。對於DML
陳述頻繁的情況,它不太可能適用,但如果安全性比性能更重要,那麼就去做吧。
以下是您的選擇最少的常見(會計)情況:「允許插入到訂單項文件夾中,以便給定的一組插入的總金額列爲0」。你可以用約束觸發器來做到這一點,或者通過破壞1NF來實現這一點,但是第一種快速和骯髒的方法是強制所有插入函數通過函數。這並不意味着也不會做約束,但這意味着單行約束本身是不夠的。 –