2010-06-09 4 views
2

이것은 나의 첫 번째 게시물입니다! 나를 참아주십시오. SQL Server에서 처리하는 방법을 이해하려고하는 업데이트 문이 있습니다.업데이트 테이블 설정 필드

UPDATE a 
    SET a.vField3 = b.vField3 
FROM tableName a 
    INNER JOIN tableName b on a.vField1 = b.vField1 
     AND b.nField2 = a.nField2 – 1 

가장 간단한 형식의 쿼리입니다.

vField1 is a Varchar 
nField2 is an int (autonumber) 
vField3 is a Varchar 

나는 WHERE 절을 남겨 두었으므로 그렇지 않은 경우 논리가 있다는 것을 이해해야합니다.

vField1은 고객 번호이고 고객은 3 개의 레코드가 있다고 말하십시오. nField2의 값은 1, 2 및 3입니다. 업데이트가 a.nField2 = 1에 관해서 더 a.nField2이없는 경우 vField3는 상태

-1 때문에 업데이트 a.nField2 = 2, b.nField2 = 1 에 관해서는 을 계속하는 경우 업데이트는 a.nField2 = 3, b.nField2 = 2

입니다. 업데이트가 a.nField2 = 2 일 때, 별칭 b는 이전 줄의 내용 (b.nField2 = 1)을 반영합니다. 그리고 SET 업데이트가 a.nField2 = 3 일 때 a.vField3 = b.vField3의 대 Varchar 값은

, 별명 b를 (해야) 라인에 이전 (b.nField2 = 2) 그리고 무엇 반영 a.vField3 = b.vField3의 Varchar 값을 설정하십시오.

프로세스가 완료되면 두 번째 레코드의 두 번째 레코드가 예상대로 나타납니다. 두 번째 레코드의 vField3 값이 vField3의 값을 첫 번째 레코드

에 반영합니다

그러나 세 번째 레코드의 vField3은 두 번째 레코드의 vField3 값을 반영하지 않습니다.

저는 이것이 SQL Server가 일종의 트랜잭션을 생성 한 다음 업데이트를 수행하고 있음을 보여줍니다.

질문 : 각 거래가 끝날 때마다 DB를 업데이트하여 각 거래가 생성 한 값을 참조하려면 어떻게해야합니까?

감사합니다. davlyo

+0

"그러나 세 번째 레코드의 vField3은 두 번째 레코드의 vField3 값을 반영하지 않습니다." 너는 무엇을 얻 느냐? 두 번째 레코드의 새 값이나 원래 값을 의미합니까? – mdma

+0

논리적 인 설정 작업보다는 커서의 관점에서 완전히 잘못된 각도에서 생각해 보았습니다. 책을 읽고 차이점을 찾아 보았지만 걱정하지 마십시오. SQL을 처음 다루는 프로그래머에게는 매우 흔한 함정입니다 시각. – Cruachan

+0

"tablename a"와 "tablename b"는 실제로 2 개의 다른 테이블이고 서로 다른 별칭을 가진 하나의 테이블이 아니라고 가정합니다. (이것은 자기 조인과 무의미한 것입니다.) – BradC

답변

1

전체 업데이트 쿼리는 하나의 작업이며, 트랜잭션의 유일한 작업 인 경우 하나의 트랜잭션입니다. 따라서 쿼리는 자체 결과를 보지 못합니다. 쿼리는 묵시적인 순서없이 작동합니다. 거의 모든 것이 한 번에 발생하는 것입니다.

또한이 자체 조인이므로 원래 두 번째/세 번째 레코드는 쿼리 실행 후 표시되지 않습니다. 하나의 레코드는 원래의 세 번째 레코드 인 "손실"되고 값 1의 레코드는 복제됩니다.

예. 당신은

mdma 1 A 
mdma 2 A 
mdma 3 B 

당신이 무엇을보고/기대 즉, 값이 될 것입니다 귀하의 업데이 트를 실행 한 후 aField3

mdma 1  A 
mdma 2  B 
mdma 3  C 

, 고객, aField2 시작?

3

첫째로 가장 중요한 것은 트랜잭션이 '연속적으로'보관되므로 트랜잭션이 논리적으로 정의 된 루프를 논리적으로 구현한다는 오해입니다. 실제로 데이터베이스의 레코드 순서는 이며 정의되지 않은 테이블은이며 은 모두입니다.이 순서대로 테이블 저장소를 생각하면됩니다. 실제로 당신은 그것을 완전히 없애려고 노력해야합니다. 그렇지 않으면 당신을 모든 종류의 함정과 나쁜 습관으로 인도 할 것입니다. 대신에 커서 트래버스가 아니라 (수학적 의미로) 집합 연산으로 실행되는 명령문을 논리적으로 생각해보십시오.

대부분의 관계형 데이터베이스에서 레코드가 ORDER BY 절없이 SELECT에 의해 검색되는 순서는 삽입 순서이지만 실제로 이것은 구현 문제이며 실제로 어떤 논리 (주문에 관심이있는 경우 항상 ORDER BY 절을 사용하여 데이터를 검색하십시오.) 특히 ANSI SQL에 따르면 데이터베이스에서 레코드를 검색하는 순서는 ORDER BY 절이 없으면 정의되지 않습니다. 기술적으로 동일한 SELECT 문의 순차적 실행에서도 일관성을 유지할 필요조차 없습니다.

따라서 관계형 데이터베이스에 대한 UPDATE 작업이 일관된 결과를 산출하기 위해서는 모든 쿼리가 단일 트랜잭션으로 작동해야합니다. 트랜잭션은 업데이트 할 레코드의 스냅 샷을 가져 와서 일관된 원자 단위 방식으로 업데이트 한 다음 결과를 다시 데이터에 적용합니다. 레코드를 돌면서 SQL을 루핑하는 논리적 개념은 없습니다.

+1

사실, 대부분의 관계형 데이터베이스에서 레코드는 'ORDER BY'가 지정되지 않으면 * 클러스터 된 인덱스 *의 순서로 검색되므로 구현 세부 사항 클러스터 된 인덱스 (나쁜 아이디어)가 없거나 항상 클러스터 된 인덱스와 동일한 순서로 삽입하지 않는 한 (FIFO 인덱스가 'IDENTITY' 열에있는 경우에만) FIFO 레코드 순서 지정 개념을 지원하지 않습니다. – Aaronaught

+0

@Aaronaught 맞습니다. 물론 대다수의 테이블에서 대부분의 데이터베이스와 함께 작동하지만 확실히 클러스터 된 인덱스는 ID 열이므로 효과적으로 삽입 순서입니다. 그러나 지적했듯이 이는 실제 아티팩트이기도합니다. – Cruachan