Oracle: 행이 없는 경우 삽입하는 방법
PL/SQL(oracle)에서 행이 없는 경우 가장 쉽게 삽입할 수 있는 방법은 무엇입니까?
나는 다음과 같은 것을 원한다.
IF NOT EXISTS (SELECT * FROM table WHERE name = 'jonny') THEN
INSERT INTO table VALUES ("jonny", null);
END IF;
근데 안 되네.
주의: 이 표에는 이름과 기간이라는 두 개의 필드가 있습니다.하지만 이름만 PK야.
INSERT INTO table
SELECT 'jonny', NULL
FROM dual -- Not Oracle? No need for dual, drop that line
WHERE NOT EXISTS (SELECT NULL -- canonical way, but you can select
-- anything as EXISTS only checks existence
FROM table
WHERE name = 'jonny'
)
10g을 사용하는 경우 MERGE 문을 사용할 수도 있습니다.그러면 행이 없으면 삽입하고 행이 있으면 무시할 수 있습니다.사람들은 "업서트"(행이 없으면 삽입하고 행이 있으면 업데이트)를 수행할 때 MERGE를 떠올리는 경향이 있지만, UPDATE 부분은 현재 옵션이기 때문에 여기서도 사용할 수 있습니다.
SQL> create table foo (
2 name varchar2(10) primary key,
3 age number
4 );
Table created.
SQL> ed
Wrote file afiedt.buf
1 merge into foo a
2 using (select 'johnny' name, null age from dual) b
3 on (a.name = b.name)
4 when not matched then
5 insert( name, age)
6* values( b.name, b.age)
SQL> /
1 row merged.
SQL> /
0 rows merged.
SQL> select * from foo;
NAME AGE
---------- ----------
johnny
이름이 PK인 경우 오류를 삽입하고 파악합니다.체크가 아닌 이 작업을 하는 이유는 여러 클라이언트를 동시에 삽입해도 작동하기 때문입니다.체크 후 삽입할 경우 해당 시간 동안 잠금을 유지하거나 오류를 예상해야 합니다.
이 암호는 다음과 같습니다.
BEGIN
INSERT INTO table( name, age )
VALUES( 'johnny', null );
EXCEPTION
WHEN dup_val_on_index
THEN
NULL; -- Intentionally ignore duplicates
END;
행이 행선지 테이블에 존재하는 것을 확인하고 싶은 경우(특히 프라이머리 키로 2개의 열이 있는 경우)에는, 이 예에서는, 행이 행선지 테이블에 존재하지 않는 경우가 있기 때문에, 선택할 필요가 없는 경우가 있습니다.
이것이 나에게 효과가 있었다.
MERGE INTO table1 D
USING (
-- These are the row(s) you want to insert.
SELECT
'val1' AS FIELD_A,
'val2' AS FIELD_B
FROM DUAL
) S ON (
-- This is the criteria to find the above row(s) in the
-- destination table. S refers to the rows in the SELECT
-- statement above, D refers to the destination table.
D.FIELD_A = S.FIELD_A
AND D.FIELD_B = S.FIELD_B
)
-- This is the INSERT statement to run for each row that
-- doesn't exist in the destination table.
WHEN NOT MATCHED THEN INSERT (
FIELD_A,
FIELD_B,
FIELD_C
) VALUES (
S.FIELD_A,
S.FIELD_B,
'val3'
)
요점은 다음과 같습니다.
- 그
SELECT
안에 있는 성명USING
블록은 항상 행을 반환해야 합니다.이 쿼리에서 반환된 행이 없으면 행이 삽입되거나 업데이트되지 않습니다.여기서 선택합니다.DUAL
그래서 항상 한 줄만 있을 거예요. - 그
ON
condition은 행을 일치시키기 위한 기준을 설정합니다.한다면ON
일치하는 항목이 없으면 INSERT 문이 실행됩니다. - 추가 가능
WHEN MATCHED THEN UPDATE
clause를 참조해 주세요.
@benoit answer의 일부를 사용하여 다음을 사용합니다.
DECLARE
varTmp NUMBER:=0;
BEGIN
-- checks
SELECT nvl((SELECT 1 FROM table WHERE name = 'john'), 0) INTO varTmp FROM dual;
-- insert
IF (varTmp = 1) THEN
INSERT INTO table (john, null)
END IF;
END;
제가 충분한 답변을 하지 못해서 죄송하지만,IF
내 코드가 이름과 나이 필드가 있는 이 예제 표보다 훨씬 더 복잡하기 때문에 확인합니다.아주 명확한 암호가 필요해고마워, 나는 많은 것을 배웠어!@benoit 답변을 받아들이겠습니다.
지금까지 주어진 완벽하고 유효한 답변 외에ignore_row_on_dupkey_index
사용할 수 있는 힌트:
create table tq84_a (
name varchar2 (20) primary key,
age number
);
insert /*+ ignore_row_on_dupkey_index(tq84_a(name)) */ into tq84_a values ('Johnny', 77);
insert /*+ ignore_row_on_dupkey_index(tq84_a(name)) */ into tq84_a values ('Pete' , 28);
insert /*+ ignore_row_on_dupkey_index(tq84_a(name)) */ into tq84_a values ('Sue' , 35);
insert /*+ ignore_row_on_dupkey_index(tq84_a(name)) */ into tq84_a values ('Johnny', null);
select * from tq84_a;
그 힌트는 타히티에서 묘사된다.
다음 구문을 사용할 수 있습니다.
INSERT INTO table_name ( name, age )
select 'jonny', 18 from dual
where not exists(select 1 from table_name where name = 'jonny');
"대체 변수 입력"을 묻는 팝을 연 경우 위의 쿼리 전에 이 팝을 사용하십시오.
set define off;
INSERT INTO table_name ( name, age )
select 'jonny', 18 from dual
where not exists(select 1 from table_name where name = 'jonny');
Merge를 사용해야 합니다.예를 들어 다음과 같습니다.
MERGE INTO employees e
USING (SELECT * FROM hr_records WHERE start_date > ADD_MONTHS(SYSDATE, -1)) h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
또는
MERGE INTO employees e
USING hr_records h
ON (e.id = h.emp_id)
WHEN MATCHED THEN
UPDATE SET e.address = h.address
WHEN NOT MATCHED THEN
INSERT (id, address)
VALUES (h.emp_id, h.address);
https://oracle-base.com/articles/9i/merge-statement
CTE 및 유일한 CTE :-)
그냥 여분의 물건을 버려라.여기 삶의 모든 경우에 대해 거의 완벽하고 장황한 형식이 있다.그리고 어떤 간결한 형식이라도 사용할 수 있습니다.
INSERT INTO reports r
(r.id, r.name, r.key, r.param)
--
-- Invoke this script from "WITH" to the end (";")
-- to debug and see prepared values.
WITH
-- Some new data to add.
newData AS(
SELECT 'Name 1' name, 'key_new_1' key FROM DUAL
UNION SELECT 'Name 2' NAME, 'key_new_2' key FROM DUAL
UNION SELECT 'Name 3' NAME, 'key_new_3' key FROM DUAL
),
-- Any single row for copying with each new row from "newData",
-- if you will of course.
copyData AS(
SELECT r.*
FROM reports r
WHERE r.key = 'key_existing'
-- ! Prevent more than one row to return.
AND FALSE -- do something here for than!
),
-- Last used ID from the "reports" table (it depends on your case).
-- (not going to work with concurrent transactions)
maxId AS (SELECT MAX(id) AS id FROM reports),
--
-- Some construction of all data for insertion.
SELECT maxId.id + ROWNUM, newData.name, newData.key, copyData.param
FROM copyData
-- matrix multiplication :)
-- (or a recursion if you're imperative coder)
CROSS JOIN newData
CROSS JOIN maxId
--
-- Let's prevent re-insertion.
WHERE NOT EXISTS (
SELECT 1 FROM reports rs
WHERE rs.name IN(
SELECT name FROM newData
));
저는 스테로이드제를 "만약 존재하지 않는다면"이라고 부릅니다.그래서 이게 도움이 되고 저는 대부분 그렇게 해요.
언급URL : https://stackoverflow.com/questions/3841441/oracle-how-to-insert-if-a-row-doesnt-exist
'it-source' 카테고리의 다른 글
리액트를 사용하여 HTML5 비디오의 소스 URL 업데이트 (0) | 2023.03.02 |
---|---|
Spring RestTemplate 요청에서 "Accept:" 헤더를 설정하려면 어떻게 해야 합니까? (0) | 2023.03.02 |
JSON 개체를 암호화하여 해시하려면 어떻게 해야 합니다. (0) | 2023.03.02 |
반응 선택 테스트 방법(반응 선택) (0) | 2023.03.02 |
WooCommerce Webhooks Auth (비밀 & 시그니처) - 사용방법 (0) | 2023.03.02 |