PostgreSQL EXECUTE 命令成功但表没有变化
我有以下 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。
I have the following PostgreSQL script:
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;
What I am trying to do is merge two records in a database table based on the modified time.
What script does is as follows:
For each record in table, I find all matching records by a key field named "iko" with
modified time later than the record current record.
There will one or no matches. If a match is found, I enumerate each field in the current and matching record and synchronize the fields if the latter is not null.
Script runs as expected with no errors. Also, the diagnostic result ROW_COUNT indicates 1 row is updated After the EXECUTE command in the script is called. However, when I refresh the table, I do not see the expected change.
Any ideas why?
TIA.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如所示,已成功对表进行更改,但由于脚本中的错误(我试图将非文本数据类型分配给文本变量),引发了异常,导致事务回滚。如果记录字段值不是 TEXT,则这就是脚本失败的地方。:
其中 old_value 和 new_value 是脚本中先前声明的 TEXT 变量。
如果列名已知,则可以声明一个变量,例如
它将动态保存任何数据类型。因为,列名是动态发现的,所以不能使用这样的变量。我想不出一种方法可以轻松实现这一目标,所以我选择了一种完全不同的策略。
Changes were being made to table successfully as indicated but due to a bug in the script, where I was trying to assign non-TEXT data types to a TEXT variable, exception was being thrown, causing transaction to be rolled back. This is where the script is failing if the record field value is not TEXT.:
where old_value and new_value are TEXT variables declared earlier in the script.
If the column name is known, one can declare a variable such as
which would dynamically hold any data type. Because, column name is being discovered dynamically such a variable cannot be used. I could not think of a way to easily achieve this so I chose a completely different strategy.