我有以下PostgreSQL脚本:
CREATE OR REPLACE FUNCTION merge_fields() RETURNS VOID AS $$
DECLARE
current_record airport%ROWTYPE;
new_record airport%ROWTYPE;
column_def RECORD;
old_value TEXT;
new_value TEXT;
field_name TEXT;
sql_text TEXT;
integer_var INT;
BEGIN
FOR current_record in SELECT * FROM airport LOOP
-- Match Record based on iko and modified time
SELECT * INTO new_record FROM airport WHERE
iko = current_record.iko AND mod_time > current_record.mod_time;
IF FOUND THEN
FOR column_def IN
-- Get fields for this record
SELECT ordinal_position, column_name, data_type
FROM information_schema.columns
WHERE
table_schema = 'public'
AND table_name = 'airport'
ORDER BY ordinal_position
LOOP
field_name := column_def.column_name;
IF ((field_name = 'gid') OR (field_name = 'mod_time')) THEN
ELSE
-- Get each field value for current and new record. New record is matched record.
EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO old_value USING current_record;
EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO new_value USING new_record;
IF new_value IS NOT NULL THEN
IF new_value <> old_value THEN
sql_text := 'UPDATE ' || 'airport'
|| ' SET '
|| quote_ident(field_name)
|| ' = '
|| quote_literal(new_value)
|| ' WHERE gid = '
|| current_record.gid;
-- Set current record field value same as new record field value
EXECUTE 'UPDATE ' || 'airport'
|| ' SET '
|| quote_ident(field_name)
|| ' = '
|| quote_nullable(new_value)
|| ' WHERE gid = '
|| current_record.gid;
GET DIAGNOSTICS integer_var = ROW_COUNT;
RAISE NOTICE E'Old Value\t rows affected: %\t ',integer_var;
RAISE NOTICE E'Old Value\t name: %\t value: %.\n',
field_name,
old_value;
RAISE NOTICE E'New Value\t name: %\t value: %.\n',
field_name,
new_value;
END IF;
END IF;
END IF;
-- End column enumerating loop
END LOOP;
END IF;
IF NOT FOUND THEN
END IF;
END LOOP;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
RAISE NOTICE E'Too many records match search criteria.';
WHEN OTHERS THEN
-- RAISE EXCEPTION 'airports % not found';
END;
$$
LANGUAGE plpgsql;
我要做的是根据修改的时间合并数据库表中的两条记录。 脚本的作用如下:
对于表中的每条记录,我通过一个名为“iko”的关键字段找到所有匹配的记录 修改时间晚于记录当前记录。
会有一场比赛或没有比赛。如果找到匹配项,则枚举当前匹配记录中的每个字段,并在字段不为空时同步字段。
脚本按预期运行,没有错误。此外,诊断结果ROW_COUNT表示在调用脚本中的EXECUTE命令后更新1行。但是,当我刷新表格时,我看不到预期的变化。
任何想法为什么?
TIA。
答案 0 :(得分:0)
如所示,对表成功进行了更改,但是由于脚本中的错误,我试图将非TEXT数据类型分配给TEXT变量,因此抛出了异常,导致事务被回滚。如果记录字段值不是TEXT。这是脚本失败的地方。:
-- Get each field value for current and new record. New record is matched record.
EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO old_value USING current_record;
EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO new_value USING new_record;
其中old_value和new_value是脚本中先前声明的TEXT变量。
如果列名已知,则可以声明一个变量,例如
var_name table_name.column_name%TYPE;
将动态保存任何数据类型。因为,正在动态发现列名,所以不能使用这样的变量。我想不出一种轻松实现这一目标的方法,所以我选择了一种完全不同的策略。