过了一段时间,我发现imho是一个相当快的单次合并语句,用于历史记录缓慢变化的维度类型2。
它可以在没有唯一约束的表上完美地工作。
CREATE TABLE TESTS
(
T_Key_1 NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,T_Key_2 NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,Text_Value VARCHAR2(100) /* */
,Number_Value NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,Amount NUMBER /* */
,CONSTRAINT T_PK PRIMARY KEY (T_Key_1, T_Key_2) /* Primární klíč */
)
;
历史记录表:
CREATE TABLE TEST_HISTORY
(
T_Key_1 NUMBER(38,0) DEFAULT -1 NOT NULL
,T_Key_2 NUMBER(38,0) DEFAULT -1 NOT NULL
,Text_Value VARCHAR2(100)
,Number_Value NUMBER(38,0) DEFAULT -1 NOT NULL
,Amount NUMBER
,TH_Valid_From_Date DATE DEFAULT to_date('1000-01-01','yyyy-mm-dd') NOT NULL /* SCD2 - Start of validity of record. */
,TH_Valid_To_Date DATE DEFAULT to_date('3000-01-01','yyyy-mm-dd') NOT NULL /* SCD2 - End of validity of record. */
,CONSTRAINT TH_PK PRIMARY KEY (T_Key_1, T_Key_2, TH_Valid_To_Date) using index local
)
/** Physical Options **************************************************************************************************/
partition by range (TH_Valid_To_Date) interval (NUMTOYMINTERVAL (1, 'MONTH'))
(partition P_10000000 values less than (TO_DATE ('01-01-1000', 'DD-MM-YYYY')))
ENABLE ROW MOVEMENT
;
合并:
MERGE INTO (SELECT * FROM TEST_HISTORY WHERE TH_Valid_To_Date = to_date('3000-01-01','yyyy-mm-dd')) Hst /*change only current records which are identified by TH_Valid_To_Date = to_date('3000-01-01','yyyy-mm-dd') */
USING (
SELECT * FROM (
SELECT NVL(Src.T_Key_1, Dst.T_Key_1) AS T_Key_1
,NVL(Src.T_Key_2, Dst.T_Key_2) AS T_Key_2
,Src.Text_Value
,Src.Number_Value
,Src.Amount
,CASE WHEN Src.T_Key_1 is null THEN 'D' /*delete*/
WHEN Dst.T_Key_1 is null THEN 'I' /*insert*/
WHEN (Src.Text_Value=Dst.Text_Value OR (Src.Text_Value is null AND Dst.Text_Value is null))
AND (Src.Number_Value=Dst.Number_Value OR (Src.Number_Value is null AND Dst.Number_Value is null))
AND (Src.Amount=Dst.Amount OR (Src.Amount is null AND Dst.Amount is null))
THEN 'X' /*no change*/
ELSE 'U' /*update*/ END AS Operation
FROM TESTS Src
FULL JOIN (SELECT * FROM TEST_HISTORY WHERE TH_Valid_To_Date = to_date('3000-01-01','yyyy-mm-dd')) Dst
ON (Src.T_Key_1 = Dst.T_Key_1 AND Src.T_Key_2 = Dst.T_Key_2)
)
INNER JOIN (SELECT LEVEL AS duplication FROM DUAL CONNECT BY LEVEL BETWEEN 1 AND 2) ON (duplication=1 OR Operation='U') /*need to duplicate update records so that they can go to both matched and not matched parts*/
WHERE Operation<>'X'
) Act
ON (Act.T_Key_1 = Hst.T_Key_1 AND Act.T_Key_2 = Hst.T_Key_2 AND Act.duplication=1 AND Act.operation<>'I')
WHEN MATCHED THEN UPDATE
SET
TH_Valid_To_Date = p_Load_Date - 1,
WHERE Hst.TH_Valid_To_Date = to_date('3000-01-01','yyyy-mm-dd')
WHEN NOT MATCHED THEN INSERT /*+ append */
(
T_Key_1
,T_Key_2
,Text_Value
,Number_Value
,Amount
,TH_Valid_From_Date /*Auditní sloupec*/
,TH_Valid_To_Date /*Auditní sloupec*/
) VALUES (
Act.T_Key_1
,Act.T_Key_2
,Act.Text_Value
,Act.Number_Value
,Act.Amount
,p_Load_Date /*Auditní sloupec*/
,to_date('3000-01-01','yyyy-mm-dd') /*Auditní sloupec*/
)
;
我自己也遇到了同样的问题:不能同时插入和更新记录。Oracle在首次执行联接时确定是插入还是更新记录。下面是一个简化的测试用例来说明这一点:
-- This is the table into which we will be merging data
CREATE TABLE merge_table
(
mt_col1 INTEGER NOT NULL
, mt_col2 INTEGER
);
-- Make mt_col1 unique
ALTER TABLE merge_table ADD (
UNIQUE (mt_col1)
USING INDEX);
-- This is the table from which we will be drawing the data
CREATE TABLE datasource_table
(
ds_col1 INTEGER
, ds_col2 INTEGER
);
-- Load up the data source with 10 rows (1-10)
INSERT INTO datasource_table (
ds_col1, ds_col2
)
SELECT ROWNUM r, ROWNUM r
FROM all_objects
WHERE ROWNUM < 11;
-- Create a duplicate record
INSERT INTO datasource_table (
ds_col1, ds_col2
)
VALUES (1, 1);
-- Create a record to be updated
INSERT INTO merge_table (
mt_col1, mt_col2
)
VALUES (2, 2);
COMMIT;
-- This merge will fail with a unique constraint violation because
-- an mt_col1 value of 1 does not exist. The datasource table contains
-- two entries for 1, so the merge will try to insert two mt_col1=1 records,
-- violating the unique constraint.
MERGE INTO merge_table dt
USING (SELECT ds_col1, ds_col2
FROM datasource_table) a
ON (a.ds_col1 = dt.mt_col1)
WHEN MATCHED
THEN
UPDATE SET mt_col2 = a.ds_col2 + 10
WHEN NOT MATCHED
THEN
INSERT (
mt_col1, mt_col2
)
VALUES (ds_col1, ds_col2);
-- ORA-00001: unique constraint (SYS_C0013990) violated
-- Delete one of the duplicate records and the merge succeeds
DELETE FROM datasource_table
WHERE ds_col1 = 1
AND ROWNUM < 2;
-- Merge is now successful
MERGE INTO merge_table dt
USING (SELECT ds_col1, ds_col2
FROM datasource_table) a
ON (a.ds_col1 = dt.mt_col1)
WHEN MATCHED
THEN
UPDATE SET mt_col2 = a.ds_col2 + 10
WHEN NOT MATCHED
THEN
INSERT (
mt_col1, mt_col2
)
VALUES (ds_col1, ds_col2);
-- 10 rows updated
下面的代码是Dave Koelle的AlphanumComparator的编辑版本。编辑包含将空字符串排序到列表末尾或 底部的代码。问题是 为了解决我的问题,我调查了它并找到了诸如比较器没有 等原因; 在正确的位置。我还在Java错误数据库中发现了一条评论,上面写着 java.util.Arrays.sort和java.util.Collections.sort(间接地)使用的排序算法被替换了,新
以下是SQL部分,我在调试代码时出错: ORA-00001:唯一约束主键违反T_LIAV_AGENT_STATE_APPROVAL... 这是主键约束依赖的2列AV_NAME_ID,AV_STATE... 我没有重复的数据...你认为还有其他原因吗?
ORA-00001:违反唯一约束(DatabaseName.Constraint1) 这是否是因为insert all执行同步插入而序列没有增加?我尝试使用Insert ALL仅用于新的插入(不是从源表复制到目标表),我不想对每一行使用Insert query。这是我在尝试的一种研究。
每当应用程序启动时,我总是收到以下错误消息: 将data.sql更改为: 产生以下错误消息:
作为实习的一部分,我被要求调查一个错误。一段代码正在抛出 Java . lang . illegalargumentexception:比较法违反了它的通用契约! 自定义通过查看自定义类的成员变量来比较两个自定义类: 此自定义类的 方法查看此自定义类的 成员变量。我们很难重现这种行为。我的下意识反应是将自定义中的 return 语句替换为 ,但我的团队怀疑这会解决问题。谁能提供任何见解?
下面是导致异常的代码块,如所示, 代码: 例外情况: 当我将相同的代码作为独立程序运行时,该问题从未出现。这里的比较器有什么问题?有没有办法在独立代码中重现该问题? 这个问题只在Java 1.7上出现,因为Arrays.sort上的实现发生了变化