2013-10-29 3 views
0

저는 현재 웹 사이트에서 PHP와 SQL로 작업하고 있습니다. 사용자 (계정), 조직 및 조직을 계정에 연결하는 관계형 테이블이 있습니다 (다 대다 관계)이 SQL 쿼리를 구성하는 올바른 방법입니까?

데이터베이스에서 계정을 삭제할 때 SQL 쿼리는 모든 조직을 삭제해야합니다. 삭제 된 계정이 조직에 연결된 유일한 계정 인 경우 계정이 연결됩니다.

저는 비교적 SQL에 익숙하지 않으며 위의 조건에서 조직 테이블에서 조직을 삭제해야하는 쿼리를 작성했습니다.

'DELETE FROM TBL_ORGANISATIONS WHERE id = (
    SELECT org_id FROM TBL_AFFILIATIONS WHERE account_email = :email AND (
     SELECT COUNT(*) FROM TBL_AFFILIATIONS WHERE org_id IN (
      SELECT org_id FROM TBL_AFFILIATIONS WHERE account_email = :email 
     ) 
    ) = 1 
)' 

이이 쿼리를 구성하는 올바른 방법인가, 아니면이 일을 명확하게/더 효율적인 방법이 여기있다 : 내 쿼리입니다? 이전에 언급했듯이 저는 SQL에 익숙하지 않고이 같은 쿼리를 작성하는 데 유용한 모든 SQL 키워드의 개념을 아직 파악하지 못했습니다 (JOIN 등)

모든 조언을 위해 미리 감사드립니다. 당신이 제공 할 수 있습니다.

By 덧붙여 : 나는 PDO를 사용하고 있습니다. 궁금한 분들을위한 이메일입니다.

답변

0

foreign key constraints이있는 경우 소속 레코드가 여전히 삭제할 조직 레코드를 가리 키므로이 명령문은 실패합니다.

ON DELETE CASCADE을 사용하면 Mihai가 (지금 삭제 된) 댓글에서 제안한 것처럼 조직을 삭제할 수 있지만 그렇게하려면 조직에 연결된 제휴가 하나만 있는지 확인해야합니다.

이 경우 조직의 ID를 먼저 쿼리해야합니다. 어쨌든 삭제할 계정의 세부 사항을 알기 때문에 어쨌든 손에 넣을 수 있습니다. 먼저 계정을 삭제하고이처럼 보이는 문으로, 필요한 경우 다음 조직을 삭제 :

개인적으로
DELETE FROM TBL_ORGANISATIONS o 
WHERE 
    o.id = :ThatIdYouQueriedBefore AND 
    NOT EXISTS (SELECT 'x' FROM TBL_AFFILIATIONS a.org_id = o.id); 

보이는 작은 실수는 당신을 요할 수 있으므로 나는, 계단식 삭제의 큰 팬이 아니에요 많은 데이터가 있지만 사용하더라도 사용자가이 특정 사례를 훨씬 쉽게 만드는 것은 아닙니다.

+0

답장을 보내 주셔서 감사합니다. MyISAM을 테이블 엔진으로 사용하고 있기 때문에 외래 키는 사용하지 않았지만 권장 사항에 따라 엔진을 InnoDB로 변경하고 두 테이블 간의 관계를 생성하는 올바른 방법처럼 외래 키를 추가했습니다. 현재 외래 키가 사용되고 있기 때문에 좋은 해결책 인 것 같습니다. 감사합니다 –

0

두 논리 쿼리를 수행 할 것이라고 생각합니다. 삭제가 항상 함께 발생하도록 보장해야하는 경우 트랜잭션을 랩핑하고 롤백을하지 않으면 자유롭게 감싸 야합니다.

첫째,

DELETE tbl_account,tbl_affiliations 
FROM tbl_account INNER JOIN tbl_affiliations 
    ON tbl_account.account_email = tbl_affiliations.account_email /* I am assuming join condition here, perhaps there is an id to be used instead */ 
WHERE tbl_account.acount_email = ? 

그런 다음 계정 및 단일 쿼리와 조직 소속의 계정 (여기에 내가 계정 테이블 이름을 가정하고) 모두를 삭제, 삭제 고아 기관 :

DELETE tbl_organizations 
FROM tbl_organizations LEFT JOIN tbl_affiliations 
    ON tbl_organizations.org_id = tbl_affiliations.org_id 
WHERE tbl_affiliations.org_id IS NULL 

마지막 쿼리는 계정 별 정보에 종속되지 않으므로 조직 삭제가 계정과 동시에 발생하지 않아도되므로 비동기 프로세스를 실행하여 고아 조직을 정리하는 것이 좋습니다. 삭제.

이 방법의 장점은 조직과 연결된 여러 계정이 있는지 여부에 관계없이 첫 번째 쿼리를 사용하여 동일한 방식으로 사용자 계정을 잠재적으로 항상 삭제할 수 있다는 것입니다. 따라서 조직과 연관된 단일 계정이있는 경우를 찾기 위해 추가 응용 프로그램 논리 또는 SQL SELECT 하위 조회가 필요하지 않습니다.

+0

답장을 보내 주셔서 감사합니다. 현재 외래 키 제약 조건을 사용하고 있기 때문에 조직 테이블과 제휴 테이블 간의 관계로 인해 이것이 작동하지 않을 수도 있습니다. 그러나 외래 키를 추가하지 않았다면 좋은 해결책 인 것 같습니다. 감사합니다. 나는 당신을 업신 여기지만 아직 명성이 없다. –

+0

@BenGuest 글쎄, 당신은 정말로 당신이 그것을 사용하는 방식으로 organization 테이블과 affiliations 테이블 사이에 외래 키 제약 조건을 가져서는 안된다. 어쨌든 IMO는 이런 종류의 로직이 가능할 때 (그리고 성능면에서 합리적) 애플리케이션 레이어에서 구현되어야하기 때문에 개인적으로 외래 키 제약 조건의 팬이 아닙니다. 즉, 쿼리 기간 동안 외래 키 제약 조건을 해제 할 수 있습니다. –

+0

Im을 사용하는 것이 좋은 생각이 아닌 이유를 잘 모르겠다. 외래 키가 있으면 가입 이메일 테이블이 계정 이메일 주소가 변경된다고 (계정 테이블의 기본 키임) 말하면 가입 테이블이 자동으로 업데이트됩니다. PHP에서 별도의 쿼리를 통해이 작업을 수행 할 수 있다고 생각하지만 데이터베이스 엔진에서이 작업을 처리하도록 할 수 있습니다. 외래 키를 가지고 쿼리를 작성하여 데이터베이스의 다른 데이터를 작성하기가 더 어렵거나/위험 할 수 있습니다 (즉, 실수로 다른 데이터를 삭제할 가능성이 높음)? –

0

한 번에 두 테이블에서 데이터를 삭제하려고하면이 작업을 시도 할 수 있습니다. 여기

DELETE from TBL_ORGANISATIONS TO JOIN TBL_AFFILIATIONS TA 
    ON(TO.id=TA.org_id) where TA.account_email=:email; 

, 우리는 where 절 곳 TA.account_email를 사용하여 (예 : ID) 및 foriegn 키 TA (즉, ORG_ID)의 기본 키를 사용하여 두 개의 테이블 TBL_ORGANISATIONS 및 TBL_AFFILIATIONS에서 행을 삭제하려고하고 조건을 추가 = : 이메일.

+0

글쎄, 난 정말 3 테이블에서 데이터를 삭제하려고합니다 : account_to_delete's_email 이메일 account_to_delete's_email, account_email = account_to_delete's_email 어디 제휴 테이블에서 모든 행을 삭제 계정 테이블에서 행을 삭제하고 마지막으로 조직 테이블에서 행을 삭제 조직 제휴 테이블에 참조가 없다. –

관련 문제