[SQL] 기본 키 위반 오류 후 거래를 계속
SQL기본 키 위반 오류 후 거래를 계속
나는 로그 파일에서 데이터베이스로 기록의 대량 삽입을하고있는 중이 야. 때때로 (~ 모든 천 중 1 행) 행 중 하나는 기본 키를 위반하고 트랜잭션이 실패합니다. 현재, 사용자가 수동으로 고장의 원인이 된 파일을 통해 이동하고 다시 수입하기 전에 문제가되는 행을 제거 할 수있다. 이러한 파일의 수백이 불가능하다 가져올 수 있다는 것을 감안할 때.
내 질문 : 어떻게 이미 존재하는지 각 행하기 전에 SELECT 문을 할 필요없이, 기본 키 제약 조건을 위반하는 것입니다 레코드의 삽입을 건너 뛸 수 있습니다?
참고 : 나는 매우 비슷한 질문 # 1054695 알고있다, 그러나 SQL 서버의 특정 응답 것으로 보인다 나는 (파이썬 / psycopg2를 통해 수입) PostgreSQL을 사용하고 있습니다.
해결법
-
==============================
1.또한 트랜잭션 세이브 포인트를 사용할 수 있습니다.
또한 트랜잭션 세이브 포인트를 사용할 수 있습니다.
Pythonish 의사는 애플리케이션 측으로부터 도시이다 :
database.execute("BEGIN") foreach data_row in input_data_dictionary: database.execute("SAVEPOINT bulk_savepoint") try: database.execute("INSERT", table, data_row) except: database.execute("ROLLBACK TO SAVEPOINT bulk_savepoint") log_error(data_row) error_count = error_count + 1 else: database.execute("RELEASE SAVEPOINT bulk_savepoint") if error_count > error_threshold: database.execute("ROLLBACK") else: database.execute("COMMIT")
편집 : 여기 (SQL 문 접두사 ">") 문서의 예에 약간의 변화에 따라 psql의의 행동이의 실제 예입니다 :
> CREATE TABLE table1 (test_field INTEGER NOT NULL PRIMARY KEY); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "table1_pkey" for table "table1" CREATE TABLE > BEGIN; BEGIN > INSERT INTO table1 VALUES (1); INSERT 0 1 > SAVEPOINT my_savepoint; SAVEPOINT > INSERT INTO table1 VALUES (1); ERROR: duplicate key value violates unique constraint "table1_pkey" > ROLLBACK TO SAVEPOINT my_savepoint; ROLLBACK > INSERT INTO table1 VALUES (3); INSERT 0 1 > COMMIT; COMMIT > SELECT * FROM table1; test_field ------------ 1 3 (2 rows)
값 3이 여전히 동일한 트랜잭션 내부 오류 후 삽입합니다!
SAVEPOINT에 대한 문서는 http://www.postgresql.org/docs/8.4/static/sql-savepoint.html이다.
-
==============================
2.나는 당신의 고유의 위반에 예외를 잡기 위해 저장 프로 시저를 사용합니다. 예:
나는 당신의 고유의 위반에 예외를 잡기 위해 저장 프로 시저를 사용합니다. 예:
CREATE OR REPLACE FUNCTION my_insert(i_foo text, i_bar text) RETURNS boolean LANGUAGE plpgsql AS $BODY$ begin insert into foo(x, y) values(i_foo, i_bar); exception when unique_violation THEN -- nothing return true; end; $BODY$; SELECT my_insert('value 1','another value');
-
==============================
3.당신은 예외를 (CR 커서입니다) 제기 코드 앞에 점을 저장에 거래 롤백 또는 롤백을 수행 할 수 있습니다 :
당신은 예외를 (CR 커서입니다) 제기 코드 앞에 점을 저장에 거래 롤백 또는 롤백을 수행 할 수 있습니다 :
name = uuid.uuid1().hex cr.execute('SAVEPOINT "%s"' % name) try: # your failing query goes here except Exception: cr.execute('ROLLBACK TO SAVEPOINT "%s"' % name) # your alternative code goes here else: cr.execute('RELEASE SAVEPOINT "%s"' % name)
이 코드는, 그렇지 않으면 당신이 오류 메시지가 나타날 것 트랜잭션을 실행이 가정합니다.
장고 PostgreSQL의 백엔드 psycopg에서 직접 커서를 만듭니다. 어쩌면 미래에 그들은 odoo의 커서 유사한 장고 커서에 프록시 클래스를 확인합니다. 그들은 다음 코드 (자기가 커서입니다)로 커서를 확장 :
@contextmanager @check def savepoint(self): """context manager entering in a new savepoint""" name = uuid.uuid1().hex self.execute('SAVEPOINT "%s"' % name) try: yield except Exception: self.execute('ROLLBACK TO SAVEPOINT "%s"' % name) raise else: self.execute('RELEASE SAVEPOINT "%s"' % name)
그 방법은 문맥이 코드를 더 쉽게, 그것은 것입니다 :
try: with cr.savepoint(): # your failing query goes here except Exception: # your alternative code goes here
거래 물건이 없기 때문에 코드가 더 읽을 수 있습니다.
-
==============================
4.아니면 실패 행이 성공적인 것보다 다른 경로를 가지고 SSIS를 사용 할 수 있습니다.
아니면 실패 행이 성공적인 것보다 다른 경로를 가지고 SSIS를 사용 할 수 있습니다.
다른 데이터베이스를 사용하고 있기 때문에 당신은 준비 테이블에 파일 삽입을 대량 후 기존의 ID가없는 레코드 만 선택하는 SQL 코드를 사용할 수 있습니까?
from https://stackoverflow.com/questions/2370328/continuing-a-transaction-after-primary-key-violation-error by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 MIN 또는 MAX에서 널 (null) 값을 포함 할 수 있습니까? (0) | 2020.05.13 |
---|---|
[SQL] EF 핵심 엔티티 테이블 구조를 참조 카테고리 부모 ID 자체지도 (0) | 2020.05.13 |
[SQL] 업데이트 쿼리 내에서 SELECT를 사용하여 (0) | 2020.05.12 |
[SQL] 사용 된 SELECT 문은 열을 다른 수 있습니다 (REDUX를!) (0) | 2020.05.12 |
[SQL] 배쉬 스크립트는 MySQL의 값을 삽입 (0) | 2020.05.12 |