2012-10-14 2 views
0

어제 뭔가 알게되었습니다. 이 코드에서 업데이트중인 테이블에 레코드가 없으면 서버가 중단되고 시간 초과 오류 또는 그와 관련된 오류가 발생하지 않습니다. 두 번째 테이블의 레코드를 사용하면 코드가 올바르게 작동합니다. 아무것도 - 두꺼비의 업데이트 쿼리를 실행하는 레코드가 없을 때 사람이 무엇을 기대 않기 때문에 나는이를 생각하고테이블이 비어있을 때 레코드 업데이트 - CF가 응답하지 않습니다.

<cfquery name="getSomething"> 
    SELECT one, two 
    FROM some_table 
    WHERE conditions = 'my conditions' 
</cfquery> 
<cfloop query="getSomething"> 
    <cfquery name="updateSomethingElse"> 
     UPDATE other_table 
     SET three = 'my value' 
     WHERE four = #getSomething.one# 
     AND five = #getSomething.two# 
    </cfquery> 
    <!--- always run an insert ---> 
    <cfquery name="insertSomething"> 
     INSERT INTO other_table 
     (columns) 
     VALUES 
     (values) 
    </cfquery> 
</cfloop> 

는 CF의 문제입니다.

나는 첫 번째 테이블의 레코드 수를 얻을 수있는 쿼리를 실행하고 레코드 개수가 0보다 큰

이 오라클 (10)를 사용하고, CF 9.02 경우에만 업데이트 쿼리를 실행하여 고정 핫픽스와 함께.

참고 : select 쿼리는 2K/20K 레코드 사이에서 반환됩니다. 두 번째 테이블에 기존 레코드가 있으면 업데이트 및 삽입 쿼리가 모두 올바르게 실행됩니다. 업데이트 쿼리를 제거하면 두 번째 테이블에 레코드가 있는지 여부에 관계없이 삽입 쿼리를 실행할 수 있습니다.

편집 : 아래 제안 된대로 루프에서 업데이트 및 삽입 쿼리를 모두 이동하는 방법을 살펴 보겠습니다. 나는 여전히 (서버가 두 번째 테이블에 레코드가없는 상황에 처한 이유에 대한) 원래 질문이 아직 답변되지 않았다고 생각한다.

+0

_ ". 테이블의 레코드와는 코드가 잘 작동"_ - 아니 그렇지 않은; cfloop의 query 속성에 닫는 인용 부호가 없습니다. 쿼리 루프는 레코드가 없으면 본문을 실행하지 않으므로 여기에 표시된 것보다 더 많은 쿼리 루프가 있어야합니다. –

+0

이것은 문제를 설명하기 위해 타이핑 한 것입니다. 실제 코드는 정확했습니다. 그리고 제가 언급했듯이, 테이블에 레코드가있을 때 괜찮습니다. 또한 select 쿼리는 int로 전달 된 params에 따라 2K와 20K 레코드를 반환합니다. – earachefl

+0

_actly_ 코드 (_only_ 민감한 정보/반복 정보가 새 니타 이징/스 니핑 됨)를 제공하면 항상 쉽고 명확 해집니다. –

답변

2

UPDATE 문에 도달하지 않기 때문에 반환 된 레코드가 없으면 서버가 UPDATE 상태에서 중단되지 않습니다. UPDATE 쿼리를 제거하고 레코드가 반환되지 않을 때 루프에서 '레코드'만 출력하는 것이 좋습니다. 서버가 여전히 멈춰야하므로 문제가되는 UPDATE를 배제 할 수 있습니다.

하지만 기록에 대한 수표를 추가하지 않는 이유는 무엇입니까?

<cfquery name="getSomething"> 
SELECT one, two 
FROM some_table 
WHERE conditions = 'my conditions' 
</cfquery> 

<cfloop query="getSomething"> 
<cfif getSomething.RecordCount> 
    <cfquery name="updateSomethingElse"> 
    UPDATE other_table 
    SET three = 'my value' 
    WHERE conditions = 'other conditions' 
    </cfquery> 
</cfif> 
<cfquery> 
INSERT 
</cfquery> 
</cfloop> 

두 테이블을 함께 조인하는 UPDATE 문을 사용하는 것이 좋습니다. 12,000 건의 업데이트로 데이터베이스를 조회하는 경우 아래 코드를 실행하는 데 훨씬 적은 시간이 소요될 수 있습니다.

이 걸려 이유에 관해서는
<cfquery name="updateSomethingElse"> 
UPDATE other_table 
SET three = 'my value' 
FROM some_table, other_table 
WHERE some_table.id = other_table.id 
AND some_table.conditions = 'my conditions' 
AND other_table.conditions = 'other conditions' 
</cfquery> 
<cfquery name="getSomething"> 
INSERT INTO other_table (one, two) 
SELECT one, two 
FROM some_table 
WHERE conditions = 'my conditions' 
</cfquery> 
+0

글쎄, 내가 루프를 돌리고있는 이유는 매번 루프를 통과해야하는 업데이트 후에도 삽입 쿼리를 수행하고 있기 때문이다. 20K 레코드가 있더라도 1 분 안에 20K 업데이트 및 20K 인서트가 발생합니다. 이는 이전 레코드가 업데이트되고 (기본적으로 비활성 상태가 됨) 새 레코드가 동시에 삽입되며 일반적으로 관리자가 1 년에 한 번만 실행하는 관리 기능을 의미합니다. 업데이트 진술에 대한 귀하의 제안을 살펴 보겠습니다. 가능성이 있다고 생각합니다. – earachefl

+0

질문에 더 잘 맞도록 내 답변이 업데이트되었습니다. 또한 INSERT/SELECT 문을 수행 할 수 있으므로 반환되는 레코드 수에 관계없이 2 개의 쿼리 만 실행합니다. –

+0

대상 테이블이 동일하기 때문에 병합을 실행하여 삽입 또는 업데이트 할 수도 있습니다. – iivel

1

는, 지금까지 데이터베이스에 만들어지고 전화 또는이 두 번째 쿼리가 평가 될 때 [당신이 두 번째 테이블이 비어있는 것을 의미 같은데요] 걸려 . 이와 같은 문제를 기억하는 것처럼 보이지만 동일한 방법을 사용하여 해결할 수 있습니다. 두 번째 cfquery는 subselect를 사용하고 select에서 업데이트 할 수 있기 때문에 꼭 필요한 것은 아닙니다. 업데이트의 조건이 첫 번째 쿼리에서 생성 된 경우 카티 샨 제품이 생성되어 실행 시간이 지나치게 길어질 수 있습니다 (시간 제한 설정에 따라 실제로 시간 초과되지 않음).

대체 접근법은 루프에 대한 필요성을 제거하고 데이터베이스가하는 일을 데이터베이스에서 수행 할 수 있기 때문에 전체 쿼리에 관심이 있습니다.

UPDATE other_table OT 
SET OT.three = (SELECT one 
       FROM some_table ST 
       INNER JOIN OT 
         ON OT.whatever = ST.stuff 
       WHERE conditions = 'conditions') 
WHERE other_conditions = 'other conditions' 

당신이로 병합 명령을 사용할 수있어 업데이 트 다음 초기 테이블에서 선택하거나 삭제할 수있는 기능을 필요로하여 명확하게 문을 감안할 때 : 오라클은 선택에 따라 업데이트가 그래서 당신이 줄 수 있습니다 너, 병합의 행동은 효과적으로 삽입 (또는 업서 트라고도 함) 업데이트입니다. Wikipedia 링크는 실제로 구문을 구조화하는 방법에 대해 매우 분명합니다.

http://en.wikipedia.org/wiki/Merge_(SQL)

관련 문제