Sql 以更可读的格式显示此元数据表的策略?
我有一个基本上是“元数据表”的表;它记录对另一个表的数据所做的更改,另外还有一个警告:由于设计缺陷,我们不能执行SQLSql 以更可读的格式显示此元数据表的策略?,sql,oracle11g,oracle-sqldeveloper,Sql,Oracle11g,Oracle Sqldeveloper,我有一个基本上是“元数据表”的表;它记录对另一个表的数据所做的更改,另外还有一个警告:由于设计缺陷,我们不能执行SQLupdate操作,当行上只有一个字段发生更改时,我们必须删除然后重新插入行,并且每行只记录每个字段。例如: Table Customers: Customer ID | Customer Name | Customer Address | 001 | John F | 213 Privet Drive 002 | Kyle A | 16 Gammon Road Table C
update
操作,当行上只有一个字段发生更改时,我们必须删除然后重新插入行,并且每行只记录每个字段。例如:
Table Customers:
Customer ID | Customer Name | Customer Address |
001 | John F | 213 Privet Drive
002 | Kyle A | 16 Gammon Road
Table Customers-History:
TIMESTAMP | OPERATION | FIELD NAME | FIELD VALUE
1-Dec-2010 19:54:1232| INSERT | CUSTOMER ID | 001
1-Dec-2010 19:54:1232| INSERT | CUSTOMER NAME | Kyle A
1-Dec-2010 19:54:1500| INSERT | CUSTOMER ADDRESS | 10 Gammon Road
2-Dec-2010 09:54:9432| DElETE | CUSTOMER ID | 001
2-Dec-2010 09:54:9500| DELETE | CUSTOMER NAME | Kyle A
2-Dec-2010 09:54:9600| DELETE | CUSTOMER ADDRESS | 10 Gammon Road
2-Dec-2010 09:54:9800| INSERT | CUSTOMER ID | 001
2-Dec-2010 09:54:9900| INSERT | CUSTOMER NAME | Kyle A
2-Dec-2010 09:54:9600| INSERT | CUSTOMER ADDRESS | 16 Gammon Road
2-Dec-2010 09:55:9921| DELETE | CUSTOMER NAME | Josh C
2-Dec-2010 09:55:9925| DELETE | CUSTOMER ADDRESS| 2 Agin Court
因此,从上面的例子中,我们看到一位名叫Kyle a的客户,他住在金门路10号,第二天地址被更新为金门路16号。一段时间后,客户Josh C被删除。您会注意到,虽然只编辑了客户地址
,但由于整行被删除,客户名称
也被注册为已删除并重新插入。因此,名称字段看起来好像已更新,但实际上并未更新-它是客户地址
编辑的一部分
我想根据操作的时间戳和字段名将删除
-插入
操作分组为更新
,向用户显示这实际上是一个更新
操作,并且可能只显示更新的字段-在这种情况下,从客户地址
隐藏结果
我的问题是,这在SQL级别上是否可能(因为它返回结果最快)?如果没有,我可以在SQL查询中探索哪些策略来返回尽可能最小的相关结果,然后将这些结果传递给另一个组件进行处理?如果我理解正确,插入或删除被视为
更新,如果且仅当:
插入
作为更新
-记录被删除后被插入
DELETE
asUPDATE
-记录在插入之前已被删除
在所有其他情况下,您都希望呈现
作为独立的INSERT
或DELETE
操作,无论哪种情况
虽然[3]很简单,但[1]和[2]会带来问题,因为您需要一个键来识别相同的记录是否在删除后插入,以便您可以将其标记为更新。只有在插入
或删除
过程中存在一个不能更改的键时,才能确保此处的相同部分。由于这个问题的性质,我认为关键必须是NATURAL
,而不是代理
在这种情况下,可以使用以下策略:
步骤1:使用删除前面或插入后面的标志数据查询所有主键行
步骤2:将所有插入或删除记录标记为满足我们标准的更新
步骤3:将当前为2条记录的更新记录(由于步骤2)平铺为一条记录
步骤4:使用UNION根据步骤3的结果集中的操作时间戳检索其他字段(示例中的客户地址)
假设Customer Name
是您示例中缺少更好列的关键,下面的伪SQL代码概述了解决问题核心的方法[仅步骤1和2。步骤3和4应该足够简单,可以添加到外部查询中]
SELECT /* 2nd step: Modify Operations to 'Update' if this INSERT id done after a DELETE or DELETE done afteran INSERT */
CASE
WHEN
OPERATION='INSERT' AND IS_DELETE_PRECEDING_FLAG=1
THEN
'UPDATE'
WHEN
OPERATION='DELETE' AND IS_INSERT_FOLLOWING_FLAG=1
THEN
'UPDATE'
ELSE OPERATION
END AS OPERATION,
FIELDNAME,
FIELDVAL,
OPDATE
(
SELECT /* 1st step: Query all PK records and also the flag information commented below */
OPERATION,
FIELDNAME,
FIELDVAL,
OPDATE,
IS_DELETE_PRECEDING_FLAG, --Pseudo Column using Oracle analytics, grouped using the customer name. Is 1 when there is a DELETE preceding, 0 otherwise
IS_INSERT_FOLLOWING_FLAG --Pseudo Column using Oracle analytics, grouped using the customer name. Is 1 when there is a INSERT following, 0 otherwise
FROM
CUST_TAB_HIST
WHERE
FIELDNAME='CUSTOMER NAME' --Assuming this is the primary key
)
;
您能详细说明一下您希望这个可读的输出在您的问题中是什么样子的吗?@我看不到编辑,即,“我想根据操作的时间戳和字段名将删除插入操作分组为更新,向用户显示这实际上是一个更新操作,并且可能只显示已更新的字段-在这种情况下,从客户地址隐藏结果。“您提供的样本时间戳数据是否表示插入
或删除
发生的时间?如果是,则可能需要将它们修复为同一记录上两个字段的插入
或删除
,因为这些操作是原子操作,因此不可能在不同的时间戳上发生。在您的情况下,相同记录的字段的秒数似乎有所不同。您希望允许操作将它们分组在一起的时间有多近?当然,窗口越大,假阳性的可能性越大,假阴性的可能性越低。是否有某种东西将历史记录表的行与实际表的主键(我假设是客户ID
)联系起来?例如,您知道最后两次删除受影响的Customer ID
002,而其他受影响的Customer ID
001吗?@时间戳不是虚构的,根本不反映我的真实数据,但您是对的,它们是原子的。因此,一般来说,它们之间的间隔不应超过1s(可能是因为蝴蝶干扰了太阳辐射,导致一些数据包重新发送或其他原因),谢谢您的回答。最后,我们决定抓取所有内容并在另一个业务层组件上进行排序,因为太多的事情可能会出错,并且表将来可能会变得更复杂。你有什么建议可以减少返回的行数,这样我们就只能得到相关的行了吗?不必太复杂,欢迎你。请你澄清一下“相关的”是什么意思?至于减少行数,您可以在步骤4之后进行透视,而不是每行显示每个字段,只显示一条包含所有必需字段的完整记录。仅获取与正在更新的字段相对应的记录,并删除仅因为另一个字段已更新而存在的记录。