2015-03-05 15:35:35 IST HINT No function matches the given name and argument types. You might need to add explicit type casts. - postgresql
I have facing problem in the below function of postgres, I have tried by looking many examples like this, which has been uploaded by many others but still I dint find the solution. Please help me out.
I know the below function is lengthy. Thanks
CREATE OR REPLACE FUNCTION adt_transfer_patient(in_hospital_id integer, in_reg_no character varying(50), in_admt_id numeric, in_transfer_type character varying(25), in_release_cause character varying(1), in_user_id character varying(50), in_new_dept_id integer, in_new_unit_id integer, in_new_ward_id integer, in_consultant integer, in_icd character varying(50), in_icd_desc character varying(50))
RETURNS integer AS
$BODY$
DECLARE
temp_dept_id integer;
temp_unit_id integer;
temp_ward_id integer;
return_int integer;
temp_bed_id integer;
temp_present_position character varying;
temp_is_blocked integer;
max_diagnos_id integer;
tmp_bedno text;
tmp_ward text;
temp_node_ward_id integer;
tmp_tot_record integer;
tmp_int_var integer;
icdcode character varying(25);
disease_remark character varying(200);
BEGIN
temp_is_blocked=0;
--Present Department,Unit,Ward and Bed
SELECT dept_id INTO temp_dept_id FROM department_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL ORDER BY admission_date DESC limit 1;
SELECT unit_id INTO temp_unit_id FROM unit_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL;
SELECT ward_id INTO temp_ward_id FROM ward_admission WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND release_date IS NULL
ORDER BY admission_date DESC limit 1;
SELECT COALESCE(bedid,'0') INTO temp_bed_id FROM bed_occupancy WHERE hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id AND releasedate IS NULL;
--Tranfer Department
IF in_transfer_type = 'D' THEN
UPDATE department_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
INSERT INTO department_admission(hospital_id,reg_no,ipd_admission_id,dept_id,admission_date,admission_time,userid)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_dept_id,current_timestamp,current_time,in_user_id);
END IF;
--Transfer Unit
IF in_transfer_type = 'D' OR in_transfer_type = 'U' THEN
UPDATE unit_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
INSERT INTO unit_admission(hospital_id,reg_no,ipd_admission_id,unit_id,admission_date,admission_time,userid)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_unit_id,current_timestamp,current_time,in_user_id);
END IF;
--Transfer Ward
IF in_transfer_type = 'D' OR in_transfer_type = 'U' OR in_transfer_type = 'W' THEN
UPDATE ward_admission SET release_date=current_timestamp,release_cause=in_release_cause,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND release_date IS NULL;
IF in_transfer_type = 'W' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,temp_dept_id,temp_unit_id);
ELSIF in_transfer_type = 'U' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,temp_dept_id,in_new_unit_id);
ELSIF in_transfer_type = 'D' THEN
INSERT INTO ward_admission(hospital_id,reg_no,ipd_admission_id,ward_id,admission_date,admission_time,userid,dept_id,unit_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_ward_id,current_timestamp,current_time,in_user_id,in_new_dept_id,in_new_unit_id);
END IF;
END IF;
--Tranfer Bed
UPDATE bed_occupancy SET releasedate=current_timestamp,userid=in_user_id
WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id AND releasedate IS NULL;
--SELECT COUNT(*) into temp_is_blocked FROM mas_link_ward,ward_admission where mas_link_ward.parent_ward_id=ward_admission.ward_id
--and mas_link_ward.node_ward_id=temp_ward_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
-- SELECT COUNT(*) into temp_is_blocked FROM mas_link_ward,ward_admission where mas_link_ward.node_ward_id=ward_admission.ward_id and mas_link_ward.parent_ward_id=temp_ward_id and mas_link_ward.parent_dept_id=temp_dept_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
--SELECT node_ward_id into temp_node_ward_id FROM mas_link_ward,ward_admission where mas_link_ward.node_ward_id=ward_admission.ward_id and mas_link_ward.parent_ward_id=temp_ward_id and mas_link_ward.parent_dept_id=temp_dept_id and ward_admission.release_date is null and abs(extract(epoch from current_timestamp - admission_date)/20000)>48;
if temp_is_blocked is null then
temp_is_blocked=0;
end if;
IF temp_is_blocked>0 THEN
UPDATE mas_bed SET status='B' WHERE bedid=temp_bed_id AND hospital_id=in_hospital_id;
IF in_hospital_id=4 THEN
--*** insert record into notification table ***
select bedno into tmp_bedno from mas_bed where bedid=temp_bed_id;
select ward_name into tmp_ward from mas_ward where ward_id=temp_node_ward_id;
INSERT INTO table_notification(sl_no, notification, group_type, ward_id, dept_id, unit_id, employee_id,seen)
SELECT (SELECT COALESCE(max(sl_no),0) FROM table_notification)+row_number() OVER(),'Bed No'||tmp_bedno||' of ward '||tmp_ward||' is blocked','W',temp_node_ward_id,0,0,uid,0 FROM config.user_ward_mapping
WHERE ward_id=temp_node_ward_id;
END IF;
ELSE
UPDATE mas_bed SET status='A' WHERE bedid=temp_bed_id AND hospital_id=in_hospital_id;
END IF;
IF in_new_bed_id != 0 THEN
INSERT INTO bed_occupancy(hospital_id,reg_no,ipd_admission_id,bedid,occupancydate,occupied,userid,entrytime)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_new_bed_id,current_timestamp,'O',in_user_id,current_time);
UPDATE mas_bed SET status='O' WHERE bedid=in_new_bed_id AND hospital_id=in_hospital_id;
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,in_new_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
END IF;
IF in_new_bed_id = 0 THEN
INSERT INTO bed_occupancy(hospital_id,reg_no,ipd_admission_id,bedid,occupancydate,occupied,userid,entrytime,transfer_to_floor)
VALUES (in_hospital_id,in_reg_no,in_admt_id,-1,current_timestamp,'O',in_user_id,current_time,'Y');
--UPDATE bed_occupancy SET transfer_to_floor='Y' WHERE reg_no=in_reg_no AND ipd_admission_id=in_admt_id AND hospital_id=in_hospital_id;
END IF;
--Entry in Patient transfer log
--NOTE: Valid Entry Against Trasnfer Type only
INSERT INTO patient_transfer_log(hospital_id, reg_no, ipd_admission_id, transfer_type, transfer_date,transfer_time, from_department_id, to_department_id, from_unit_id,
to_unit_id, from_ward_id, to_ward_id, from_bed_id, to_bed_id,consultant_id)
VALUES (in_hospital_id,in_reg_no,in_admt_id,in_transfer_type,current_timestamp,current_time,temp_dept_id,in_new_dept_id,temp_unit_id,
in_new_unit_id,temp_ward_id,in_new_ward_id,temp_bed_id,in_new_bed_id,in_consultant);
IF in_transfer_type = 'D' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,in_new_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'U' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,in_new_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'W' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,temp_unit_id)||'^'||get_ward_name(in_hospital_id,in_new_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
ELSIF in_transfer_type = 'B' THEN
-- Set present Position
temp_present_position='~IPD^'||get_department_name(in_hospital_id,temp_dept_id)||'^'||get_unit_name(in_hospital_id,temp_unit_id)||'^'||get_ward_name(in_hospital_id,temp_ward_id)||'^'||get_bed_no(in_hospital_id,in_new_bed_id);
END IF;
UPDATE patient_detail SET present_position=COALESCE(present_position,' ^ ^ ^ ^')||temp_present_position,ward_id=in_new_ward_id,ward_entry_date=current_timestamp,bedid=in_new_bed_id,occupancydate=current_timestamp
WHERE reg_no=in_reg_no AND
hospital_id=in_hospital_id AND ipd_admission_id=in_admt_id;
IF in_hospital_id=4 and in_icd<>'' THEN
select count(*) into tmp_tot_record from (select unnest(string_to_array(in_icd, ',')))tbl;
tmp_int_var = 1;
WHILE tmp_int_var <= tmp_tot_record LOOP
SELECT split_part(in_icd, ',', tmp_int_var) INTO icdcode;
SELECT split_part(in_icd_desc, ',', tmp_int_var) INTO disease_remark;
IF icdcode IS NOT NULL THEN
Select coalesce(max(slno),0)+1 into max_diagnos_id FROM tran_diagnosis_log where reg_no=in_reg_no;
INSERT INTO tran_diagnosis(
reg_no, slno,icd_o,remarks,
provisional_final, doctor_id, hospital_id, ipd_admission_no, entry_source,entry_date)
VALUES (in_reg_no, max_diagnos_id,icdcode,disease_remark,'Final', in_user_id::integer, in_hospital_id, in_admt_id,'TRANSFER',current_timestamp);
INSERT INTO tran_diagnosis_log(
reg_no, slno,icd_o,remarks,
provisional_final, doctor_id, hospital_id, ipd_admission_no, entry_source,entry_date)
VALUES (in_reg_no, max_diagnos_id,icdcode,disease_remark,'Final', in_user_id::integer, in_hospital_id, in_admt_id,'TRANSFER',current_timestamp);
tmp_int_var = tmp_int_var+1;
END IF;
END LOOP;
/**--update ipd_patient_admission_detail set disease=in_pro_diagnos where hospital_id=in_hospital_id and reg_no=in_reg_no and ipd_admission_id=in_admt_id;
Select coalesce(max(slno),0)+1 into max_diagnos_id FROM tran_diagnosis_log where reg_no=in_reg_no;
if max_diagnos_id=1 THEN
INSERT INTO tran_diagnosis(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
INSERT INTO tran_diagnosis_log(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
END IF;
if max_diagnos_id>1 THEN
INSERT INTO tran_diagnosis_log(
reg_no, slno,
provisional_final, doctor_id, remarks, hospital_id, ipd_admission_no, entry_source)
VALUES (in_reg_no, max_diagnos_id,'Provisional', in_user_id::integer, in_pro_diagnos, in_hospital_id, in_admt_id,'TRANSFER');
END IF; **/
END IF;
RETURN 1;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Related
How to implement "type is <typeName> table of rowid index by" concept in postgresql to compare table data with new inserted data
I am trying to convert below piece of code from oracle to postgres(Basically the goal is to insert some records in table based on some date without overlapping and if there is date range overlapping it should raise trigger.) But after lot of efforts unable to get clue how to do it? DECLARE V_check PLS_INTEGER; BEGIN SELECT COUNT(*) INTO V_check FROM user_objects WHERE object_name = 'STORE_ROWID' AND object_type = 'PACKAGE'; IF V_check=0 THEN EXECUTE IMMEDIATE 'CREATE PACKAGE store_rowid AS' ||CHR(10)||' TYPE T_rowid IS TABLE OF ROWID INDEX BY BINARY_INTEGER;' ||CHR(10)||' T_newones T_rowid;' ||CHR(10)||' T_empty T_rowid;' ||CHR(10)||'END store_rowid;'; END IF; END; CREATE OR REPLACE TRIGGER biu_base_host BEFORE INSERT OR UPDATE ON BASE_HOST BEGIN STORE_ROWID.T_newones := STORE_ROWID.T_empty; END biu_base_host; CREATE OR REPLACE TRIGGER aiufr_base_host AFTER INSERT OR UPDATE ON BASE_HOST FOR EACH ROW BEGIN STORE_ROWID.T_newones(STORE_ROWID.T_newones.COUNT+1) := :NEW.ROWID; END aiufr_base_host; CREATE OR REPLACE TRIGGER aiu_base_host AFTER INSERT OR UPDATE ON BASE_HOST DECLARE r BASE_HOST%ROWTYPE; V_count INTEGER; V_status PLS_INTEGER; C_lockid CONSTANT PLS_INTEGER := 1001; BEGIN V_status := DBMS_LOCK.request(C_lockid,DBMS_LOCK.x_mode,release_on_commit=>TRUE); IF V_status NOT IN (0,4) THEN RAISE_APPLICATION_ERROR(-20102,'DBMS_LOCK.request ERROR, rc='||V_status); END IF; FOR i IN 1..STORE_ROWID.T_newones.COUNT LOOP SELECT * INTO r FROM BASE_HOST WHERE ROWID = STORE_ROWID.T_newones(i); SELECT COUNT(*) INTO V_count FROM BASE_HOST WHERE ROWID <> STORE_ROWID.T_newones(i) AND ZONE_ID = r.ZONE_ID AND SITE_ID = r.SITE_ID AND ORG_ID = r.ORG_ID AND (start_date BETWEEN r.start_date AND r.end_date OR end_date BETWEEN r.start_date AND r.end_date OR (start_date < r.start_date AND end_date > r.end_date)); IF V_count <> 0 THEN RAISE_APPLICATION_ERROR(-20001, 'Range from '|| TO_CHAR(r.start_date,'YYYYMMDD-HH24MISS') || ' to '|| TO_CHAR(r.end_date,'YYYYMMDD-HH24MISS')|| ' overlaps existing records'); END IF; END LOOP; END aiu_base_host;
exclusion constraint I suppose is perfect way to achieve this and I have written below code to achieve the same functionality: CREATE EXTENSION btree_gist; create table base_host( zone_id numeric(3), site_id numeric(3), org_id VARCHAR(16), start_date date, end_date date, reserved_capacity numeric(5,2), last_update date, user_id VARCHAR(32), EXCLUDE USING GIST (zone_id WITH =,site_id WITH =,org_id WITH =,daterange("start_date", "end_date") WITH &&));
stack depth limit exceeded when fired a trigger
I am trying to build a slow changing dimensional table, it track all the history of records. The schema of the table is like this: CREATE TABLE test.dim (id text, column1 text, column2 text, begin_date timestamp without time zone, is_current boolean, end_date timestamp without time zone) I defined a trigger function, and fire it before each insert action: CREATE OR REPLACE FUNCTION test.slow_change_func() RETURNS trigger AS $BODY$ DECLARE BEGIN IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim WHERE id= NEW.id AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null)) AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null)) AND is_current ) ) THEN UPDATE yang_test.dim SET (end_date, is_current) = (now(), FALSE) WHERE id = NEW.id AND is_current; INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date) VALUES ( NEW.id, NEW.column1, NEW.column2, now(), TRUE, 'infinity'::timestamp ); END IF; RETURN NULL; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; CREATE TRIGGER slow_change_trigger BEFORE INSERT ON test.dim FOR EACH ROW EXECUTE PROCEDURE test.slow_change_func(); When I try to test it, INSERT INTO test.dim (id, column1, column2, begin_date, is_current, end_date) VALUES ( 1, 'hello', 'world', now(), TRUE, 'infinity'::timestamp ) it will throw an error: stack depth limit exceeded. it looks like the function is running a loop. any suggestion s?
I think I have figure this out, this will match my requirement: CREATE OR REPLACE FUNCTION yang_test.slow_change_func() RETURNS trigger AS $BODY$ DECLARE BEGIN IF ( NOT EXISTS ( SELECT 1 FROM yang_test.dim WHERE id= NEW.id AND(column1 = NEW.column1 OR (column1 is null AND NEW.column1 is null)) AND (column2 = NEW.column2 OR (column2 is null AND NEW.column2 is null)) AND is_current ) ) THEN UPDATE yang_test.dim SET (end_date, is_current) = (now(), FALSE) WHERE id = NEW.id AND is_current; ELSE RETURN null; END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;
Having an ordinal column with no gaps
I want to have an ordinal column in which values always start from 1 and have no gaps. I have devised a solution with triggers, but I'd like to know if there is a better or more elegant way. BEFORE INSERT trigger renumbers the rows that come after the inserted value. If value is not provided or too high, it is set to row count + 1. Similarly, AFTER DELETE trigger renumbers the rows that come after the deleted value. Both triggers lock rows before changing the value. CREATE OR REPLACE FUNCTION ids_insert() RETURNS trigger AS $BODY$ DECLARE _lock_sql text; _id bigint; BEGIN IF TG_OP = 'INSERT' THEN IF NEW.id < 1 THEN RAISE EXCEPTION 'ID must be greater than zero.'; END IF; EXECUTE format('SELECT COUNT(*) + 1 FROM %I', TG_TABLE_NAME) INTO _id; IF NEW.id IS NULL OR NEW.id > _id THEN NEW.id := _id; ELSE _lock_sql := format( 'SELECT id FROM %I ' 'WHERE id >= %s ' 'ORDER BY id DESC ' 'FOR UPDATE', TG_TABLE_NAME, NEW.id ); FOR _id IN EXECUTE _lock_sql LOOP EXECUTE format('UPDATE %I SET id = id + 1 WHERE id = %s', TG_TABLE_NAME, _id); END LOOP; END IF; ELSE IF NEW.id != OLD.id THEN RAISE EXCEPTION 'Changing the ID directly is not allowed.'; END IF; END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION ids_delete() RETURNS trigger AS $BODY$ DECLARE _lock_sql text; _id bigint; BEGIN _lock_sql := format( 'SELECT id FROM %I ' 'WHERE id > %s ' 'ORDER BY id ' 'FOR UPDATE', TG_TABLE_NAME, OLD.id ); FOR _id IN EXECUTE _lock_sql LOOP EXECUTE format('UPDATE %I SET id = id - 1 WHERE id = %s', TG_TABLE_NAME, _id); END LOOP; RETURN OLD; END; $BODY$ LANGUAGE plpgsql; CREATE TABLE test ( id bigint PRIMARY KEY, ... ) CREATE TRIGGER test_insert BEFORE INSERT OR UPDATE OF id ON test FOR EACH ROW WHEN (pg_trigger_depth() < 1) EXECUTE PROCEDURE ids_insert(); CREATE TRIGGER test_delete AFTER DELETE ON test FOR EACH ROW EXECUTE PROCEDURE ids_delete();
PostgreSQL log trigger optimalization
I spent a lot of time trying to optimize our pgsql log trigger which started to be a problem. I did huge progress (from 18min to 2.5min by inserting 3M rows) but I would like to know if some pgSql masters will be able to do it even better. CREATE OR REPLACE FUNCTION table_log_trig() RETURNS trigger AS $BODY$ DECLARE col TEXT; -- Single column name to save newVal TEXT; -- New value for column oldVal TEXT; -- Old value for column colLimit TEXT[]; -- Columns that should be logged BEGIN IF TG_ARGV[0] IS NOT NULL THEN -- Trigger specifies columns to log SELECT array_agg(unnest) FROM unnest(string_to_array(TG_ARGV[0], ',')) INTO colLimit; ELSE -- Trigger with no params. Log all columns SELECT array_agg(json_object_keys) FROM json_object_keys(row_to_json(NEW)) WHERE json_object_keys NOT IN ('id', 'created_at', 'updated_at') -- Exceptions INTO colLimit; END IF; -- Loop over columns that should be saved in log FOREACH col IN ARRAY colLimit LOOP -- INSERT & UPDATE EXECUTE 'SELECT ($1).' || col || '::text' INTO newVal USING NEW; -- UPDATE IF TG_OP = 'UPDATE' THEN EXECUTE 'SELECT ($1).' || col || '::text' INTO oldVal USING OLD; END iF; -- Add only new or changed data IF newVal != oldVal OR (oldVal IS NULL AND newVal IS NOT NULL) OR (oldVal IS NOT NULL AND newVal IS NULL) THEN INSERT INTO tab_logs (record_id, field_name, old_value, new_value, created_at, created_by, action) VALUES (NEW.id, col, oldVal, newVal, NOW(), 999, 'O'); END IF; END LOOP; RETURN NEW; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100;
row_to_json() returns both column names and values; you may as well make use of these values, rather than extracting them later via dynamic SQL. I haven't thoroughly tested this, let alone benchmarked it, but here's the gist of it: CREATE OR REPLACE FUNCTION table_log_trig() RETURNS trigger AS $$ DECLARE OldJson JSONB = NULL; BEGIN IF TG_OP <> 'INSERT' THEN OldJson := to_jsonb(old); END IF; INSERT INTO tab_logs (record_id, field_name, old_value, new_value, created_at, created_by, action) SELECT new.id, key, OldValues.value, NewValues.value, now(), 999, 'O' FROM jsonb_each(to_jsonb(new)) NewValues LEFT JOIN jsonb_each(OldJson) OldValues USING (key) WHERE ( (TG_ARGV[0] IS NULL AND key NOT IN ('id', 'created_at', 'updated_at')) OR (TG_ARGV[0] IS NOT NULL AND key = ANY(string_to_array(TG_ARGV[0], ','))) ) AND OldValues.value::text IS DISTINCT FROM NewValues.value::text; RETURN NULL; END $$ LANGUAGE plpgsql VOLATILE;
PostgreSQL: compare NULL and normal value
I have a trigger in PostgreSQL CREATE OR REPLACE FUNCTION table_update_func_pk1() RETURNS trigger AS $$ DECLARE ri RECORD; old_value TEXT; new_value TEXT; BEGIN FOR ri IN SELECT column_name FROM information_schema.columns WHERE table_schema = quote_ident('public') AND table_name = quote_ident(TG_TABLE_NAME) ORDER BY ordinal_position LOOP EXECUTE 'SELECT ($1).' || ri.column_name || '::text' INTO new_value USING NEW; EXECUTE 'SELECT ($1).' || ri.column_name || '::text' INTO old_value USING OLD; IF new_value <> old_value AND ri.column_name != 'update_by' THEN INSERT INTO protokoll(datetime, operation, tabelle, field, pk1, old_value, new_value, update_by) VALUES(now(), TG_OP, TG_TABLE_NAME, ri.column_name, NEW.cfg, old_value, new_value, NEW.update_by); END IF; END LOOP; RETURN NEW; END; $$ LANGUAGE plpgsql; Sometimes if old_value is changed from NULL to normal value (or from normal value to NULL), the condition "new_value <> old_value" is NOT true but unknown. I would like ask, there is a method that I can get true in the case. Thanks.
Use is distinct from: if new_value IS DISTINCT FROM old_value and ri.column_name <> 'update_by' then ... end if;