2009-12-15 2 views
3

postgres 데이터베이스에 새 부품을 삽입하는 PHP 스크립트가 있습니다. 부품이 생성되기 전에 존재하는지 확인하고 싶습니다. 어떻게해야합니까? 나는 보통의 INSERT INTO 절을 사용하고있다.삽입 전에 확인 레코드가 있습니다

답변

6

당신 SELECT 당신이 INSERT 또는 UPDATE해야하는 경우처럼, 알고, 첫째 :

if (
    $db->fetchOne(
     'SELECT COUNT(1) FROM parts WHERE article_number = ?', 
     $p->article_number 
    ) 
) { 
    $db->update(
     'parts', 
     $p->to_array(), 
     $db->quoteInto('article_number = ?', $p->article_number) 
    ); 
} 
else { 
    $db->insert('parts', $p->to_array()); 
} 

다시 Milen의 코멘트 : 좋은 점을! 기본 PostgreSQL 트랜잭션 격리 수준 (READ COMMITTED)을 사용하면 다른 프로세스가 SELECT 다음에 "INSERT"앞에 "your"부분을 삽입 (및 커밋) 할 수 있습니다.

빌드하는 앱 종류에 따라 일반적으로 DB 예외를 잡아서 그것에 대해 뭔가를하십시오 (사용자에게 다시 시도하십시오). 또는 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE으로 갈 수도 있습니다. Transaction Isolation을 참조하십시오.

+0

Ok, SELECT else 절을 ​​사용하십시오. 나는 이것에 초보자이다, 당신은 저에게 부호를 보여 주어서 도울 수 있는가? 나는 SELECT를 할 수 있지만 else 비트는 할 수 없다. 당신의 위대한 마음에 감사드립니다. –

+0

코드 Russel을 추가했습니다. $ db는 Zend_Db_Adapter입니다. http://framework.zend.com/manual/en/zend.db.html#zend.db.adapter –

+0

동일한 article_number가 포함 된 레코드가 존재 여부 확인 직후에 삽입되면 어떻게됩니까? 삽입 (일명 경쟁 조건)? –

1

거의 충돌이 예상되지 않는 경우 : 낙관적 인 방법을 사용하고 새로운 것을 삽입하고 고유성 위반이 발생하면이를 처리하십시오. 이렇게하면 현재 트랜잭션이 실패 할 때 무효화되므로 많은 작업을 수행하는 경우 먼저 확인하는 것이 좋습니다. 이 경우 SELECT EXISTS(SELECT 1 ... FROM ... WHERE ...)을 선호합니다.

어쨌든 은 고유성 위반 가능성을 처리해야합니다. 먼저 확인해도 동시 트랜잭션이 동일한 레코드를 삽입하여 먼저 커밋 할 가능성이 있습니다.

5
insert into parts(article_number,category) 
select 'KEYB','COMPTR' 
where not exists(select * from parts where article_number = 'KEYB') 
+0

중복 된 내용을 자동으로 무시하려면 훌륭한 해결책입니다. 경쟁 조건을 겪지 않는다. 나는 그것을 직접 사용한다. – filiprem

관련 문제