2016-09-22 64 views
0

我有一個表與各種列 - 其中一些可以爲NULL(沒有默認值)。Postgresql - 在一個函數後觸發NULL列使所有有效載荷無效

所以我創建了一個觸發器,每當我在表中插入一個新值,我想觸發一個pg_notify。 (提示:我總是關於SQL的noob)。

問題是,如果只有一列可以爲空有一個空值,那麼pg_notify發出的所有有效載荷爲空。

一個很簡單的例子:

postgres=# create table example(id serial, name varchar); 
CREATE TABLE 
postgres=# create function new_example() RETURNS trigger AS $$ 
DECLARE 
BEGIN 
PERFORM pg_notify('example', 'id: ' || NEW.id || ' name: ' || NEW.name); 
RETURN new; 
END; 
$$ LANGUAGE plpgsql; 
CREATE FUNCTION 
postgres=# create trigger new_ex AFTER INSERT ON example FOR EACH ROW EXECUTE PROCEDURE new_example(); 
CREATE TRIGGER 
postgres=# LISTEN example; 
LISTEN 
postgres=# INSERT into example(name) VALUES ('a'); 
INSERT 0 1 
Asynchronous notification "example" with payload "id : 1 name: a" received from server process with PID 22349. 

這是正確的 - 我已經插入一個新的行和通知正是我期待

postgres=# INSERT into example(name) VALUES (NULL); 
INSERT 0 1 
Asynchronous notification "example" received from server process with PID 22349. 

這沒有任何意義。我會期望像Asynchronous notification "example" with payload "id : 1 name: NULL" received from server process with PID 22349.Asynchronous notification "example" with payload "id : 1 name:" received from server process with PID 22349.

我該怎麼做錯了?

回答

1

當您將字符串與||運算符連接在一起並且任何參數爲NULL時,整個表達式的計算結果爲NULL

爲了避免使用CONCAT()函數處理NULL值只需從字符串中刪除它們。

所以,代碼:

PERFORM pg_notify('example', CONCAT('id: ', NEW.id, ' name: ', NEW.name)); 

然而,這將離開下面的消息是空的,所以你可能需要使用COALESCE()功能,並拿出一些花哨的字符串,將告訴你值例如,真的是NULL而不是「空」字符串。要做到這一點的方法之一是:

PERFORM pg_notify('example', CONCAT('id: ', NEW.id, ' name: ', COALESCE(NEW.name, '[#NULL#]'))); 

但你仍然不能從真正的空值區分字符串[#NULL#]因爲他們看起來是一樣的,從NOTIFY返回的消息中。請參閱下面的不同方法。


就個人而言,我可能會稍微不同的方法去內通過創建一個審計表,並與模式和表名插入IDS,這將成爲你的目的的多個表檢查在各列空值。

+0

非常感謝 - 實際上它將被一個nodejs應用程序使用的通知,所以我認爲我會使用'COALESCE(NEW.description,'')',我會考慮''''as在nodejs端爲NULL – rpadovani