Function Postgresql 9.2触发器在存储字符串中分隔子字段
Postgresql 9.2 DB,可自动从各种机器收集数据。 DB存储所有数据,包括机器id、固件、制造商id等以及实际结果数据。在一个存储字段(Function Postgresql 9.2触发器在存储字符串中分隔子字段,function,postgresql,triggers,Function,Postgresql,Triggers,Postgresql 9.2 DB,可自动从各种机器收集数据。 DB存储所有数据,包括机器id、固件、制造商id等以及实际结果数据。在一个存储字段(varchar)中,有5个子字段,由^character分隔 ACT18!!!8246-EN-2.00013151!1^7.00^F5260046959^H1P1O1R1C1Q1L1^1 (Machine 1) 这些数据的顺序似乎因机器而异。例如机器1、2和3。上面的字符串显示固件版本,在本例中为“7.0”,并显示在子字段2中。但是,另一台机器在不
varchar
)中,有5个子字段,由^character分隔
ACT18!!!8246-EN-2.00013151!1^7.00^F5260046959^H1P1O1R1C1Q1L1^1 (Machine 1)
这些数据的顺序似乎因机器而异。例如机器1、2和3。上面的字符串显示固件版本,在本例中为“7.0”,并显示在子字段2中。但是,另一台机器在不同的子字段中发送数据-在本例中为子字段3,值为“1”
我想使用CREATE TRIGGER t_machine_id AFTER INSERT函数将值“7.0”和“1”存储在一个单独的表中的不同字段中,我可以根据数据来自的机器选择使用哪个子字段
split\u part
是执行此操作的最佳功能吗?有人能提供一个示例代码来实现这一点吗?我在文档中找不到任何内容。您需要(a)使用类似的方法拆分数据,然后(b)使用某些标准匹配哪些部分是哪些,因为您没有字段位置顺序可依赖。现在我看不到任何可靠的规则来决定什么是固件版本,什么是机器号;您不能真正说出字段machine\u number
的位置,因为如果machine 1有固件版本1
,则不会得到任何结果
给定虚拟数据:
CREATE TABLE machine_info(data text, machine_no integer);
INSERT INTO machine_info(data,machine_no) (VALUES
('ACT18!!!8246-EN-2.00013151!1^7.00^F5260046959^H1P1O1R1C1Q1L1^1',1),
('BACT/ALERT^A.00^1^^',2)
);
比如:
SELECT machine_no, regexp_split_to_table(data,'\^')
FROM machine_info;
将为您提供一个带有机器编号的拆分数据元素表,但您需要确定哪些字段是:
machine_no | regexp_split_to_table
------------+------------------------------
1 | ACT18!!!8246-EN-2.00013151!1
1 | 7.00
1 | F5260046959
1 | H1P1O1R1C1Q1L1
1 | 1
2 | BACT/ALERT
2 | A.00
2 | 1
2 |
2 |
(10 rows)
您可能会发现将regexp\u split\u替换为\u array
的输出更有用,这取决于您是否可以从字段顺序中获得任何有用的信息以及您打算如何处理数据
regress=# SELECT machine_no, regexp_split_to_array(data,'\^')
FROM machine_info;
machine_no | regexp_split_to_array
------------+------------------------------------------------------------------
1 | {ACT18!!!8246-EN-2.00013151!1,7.00,F5260046959,H1P1O1R1C1Q1L1,1}
2 | {BACT/ALERT,A.00,1,"",""}
(2 rows)
假设有两个固件版本;版本1发送code^blah^fvers^^
,版本2及更高版本发送code^fvers^blah^blah2^machineno
。然后,您可以区分这两个字段,因为您知道版本1将最后两个字段留空:
SELECT
machine_no,
CASE WHEN info_arr[4:5] = ARRAY['',''] THEN info_arr[3] ELSE info_arr[2] END AS fw_vers
FROM (
SELECT machine_no, regexp_split_to_array(data,'\^')
FROM machine_info
) string_parts(machine_no, info_arr);
结果:
machine_no | fw_vers
------------+---------
1 | 7.00
2 | 1
(2 rows)
当然,您只提供了两个示例数据,因此真正的匹配规则可能更复杂。考虑编写一个SQL函数来提取所需的字段并从数组中返回它们。为什么你不能改变上传脚本以正确地分割并填充目标表,而不是所以不需要改变触发器?我们尝试过这样做,但是数据源是如此的多样化,以至于很难从这个字符串中的机器中获取所有数据。好吧,我只能说,通过触发器进行操作将是非常高维护性和容易出错的。数据库应该存储数据,而不是决定如何解析可能(在您的情况下很可能)的无效数据。太好了-这让我走上了正确的方向。第一个字段似乎总是机器名,因此应该很容易提取。正如你所说,我需要找到一些规则,从变量字段位置提取数据。
machine_no | fw_vers
------------+---------
1 | 7.00
2 | 1
(2 rows)