SELECT의 변수 할당 평가 순서는 반환되는 행 순서와 다를 수 있습니다.어떤 상황에서 이런 일이 일어날 수 있나요?
최근에 사용자 정의 변수를 사용하여 결과 집합에서 반환된 마지막 행의 정보를 캡처하려고 했습니다.
내 말은, 예를 들어 '아론'에서 '자르크스'까지 이름 목록을 가지고 있다면
SELECT @n:=Name FROM people ORDER BY Name;
SELECT @n;
번째 두 the theSELECT
'를 반환해야 . 'Zzarx'를 반환해야 합니다.
그것은 간단한 경우이다.예상대로 동작합니다.변수 할당은 행이 클라이언트에 전송될 때와 같은 순서로 확실하게 이루어지기 때문에 마지막 할당은 마지막으로 반환된 행에 대응합니다.
하지만 질문이 더 복잡해지면 이상한 일이 일어나는 것 같습니다.
SELECT DISTINCT IFNULL(@n:=Name,'unknown') FROM people ORDER BY <some non-indexed expression> LIMIT 10;
SELECT @n;
작업을.3.16에서 두 번째 MariaDB v10.3.16에서).SELECT
첫 번째!에 의해 반환된 행과 일치하지 않습니다.(이름은NOT NULL
,IFNULL()
실제로는 용장성이지만, 이 동작을 트리거하기 위해서도 필요합니다).
이 문제가 발생하는 것은, 다음의 모든 것이 유지되고 있는 경우 뿐입니다.
SELECT DISTINCT
ORDER BY
을 수 없다- 변수 할당이 일부 식 내에서 발생합니다.
제 생각은 다음과 같습니다.
SELECT DISTINCT
을 사용하다ORDER BY (non-indexed expression)
는 컬럼 데이터를 평가한 후 명시적인 정렬 조작을 강제합니다.- 한 SQL을 할 수 있을 합니다.
SELECT @var := (expression)
@되지만 @var가 클라이언트에 전송될 때@var:=...
큰 안에 있습니다.IFNULL()
제 예에서는요.
그러나 이것은 모두 추측일 뿐이다.사용자 정의 변수의 수동 페이지에는 이러한 점에서 유용한 정보가 없습니다(MySQL도 MariaDB도 마찬가지).
@variable을 사용하여 멀티행 쿼리의 마지막 반환된 행에서 무언가를 캡처하는 것이 유용하고 매우 일반적인 트릭이라고 생각합니다만, 지금은 신뢰할 수 있을지 어떨지 모르겠습니다.을 사용하는 및 도 많이 .이 스킴은 결과 에서 @variable을 사용합니다.SELECT
.
여기 SO 담당자는 이것이 어떻게 동작해야 하는지, 구체적으로 어떤 조건에서 행 변수 할당식의 평가 순서가 실제 반환되는 행의 순서에 대응하도록 보장되는지에 대한 명확한 정보를 가지고 있습니까?
...왜냐하면 이것은 매우 중요한 것 같기 때문이다!
병리학적 문제가 약간 덜한 또 다른 예:
table t에 1000개의 행이 있다고 합니다.
SET @n:=0;
SELECT @n:=@n+1 FROM t ORDER BY 1 DESC LIMIT 5;
SELECT @n;
반환되는 결과 세트는 다음과 같습니다.
1000
999
998
997
996
그리고.
1000
한 마지막 해 주세요.@n
반환된 마지막 행에 해당되지 않으며 실제로 쿼리의 의미에 따라 이 경우 해당 행은 해당되지 않습니다.
8.0.13을 사용하고 있지 않지만, 다음 제품이 곧 출시될 예정입니다.왜 이런 일이 일어나는지 이유를 찾았군요.
----- 2018-10-22 8.0.13 일반 가용성 ----- 중요한 변경 -----
SET 이외의 스테이트먼트에서 사용자 변수를 설정하는 것은 다음과 같은 문제가 있기 때문에 권장되지 않습니다.
사용자 변수와 관련된 식에 대한 평가 순서가 정의되지 않았습니다.
변수의 기본 결과 유형은 문의 시작 부분에 있는 해당 유형을 기반으로 합니다. 이는 문의 시작 부분에 한 유형의 값을 유지하는 변수가 동일한 문에서 다른 유형의 새 값을 할당받았을 때 의도하지 않은 영향을 미칠 수 있습니다.
선택식 목록에서 값이 할당된 변수를 참조할 때 HADING, GROUP BY 및 ORDER BY 구가 예상대로 작동하지 않았습니다.이는 식이 클라이언트에서 평가되었기 때문에 이전 행의 오래된 열 값이 사용될 수 있기 때문입니다.
SELECT @var, @var 등의 구문:=@var+1은 이전 버전과의 호환성을 위해 MySQL 8.0에서 여전히 허용되지만 향후 릴리스에서는 제거될 예정입니다.
-- 「변경 로그」로부터.
DISTINCT
와와 to to to GROUP BY
.
SELECT @v := ... FROM t ORDER BY x;
1: 이 1 1 1:INDEX(x)
그러나 Optimizer는 행을 가져온 다음 정렬하도록 선택할 수 있습니다.
2: 이 2 2 2:INDEX(x)
옵티마이저는 인덱스를 기반으로 행을 가져오도록 선택합니다.
SELECT @v := ... FROM t GROUP BY w ORDER BY x;
이를 위해서는 (주문하기 위해) 두 개(그룹화 및 주문용)의 임시 테이블을 생성해야 합니다.은 @을 평가하는 것입니다.SELECT
결과를 수집한 후 그룹화와 순서를 진행합니다.따라서 평가 순서는 다음과 같이 되지 않을 것 같습니다.x
하지만 그것은 아마도w
.
★★는?PARTITIONing
의 MySQL SELECT
하지만, 만약 그것이 존재한다면?'명백한' 경우를 예로 들어 보겠습니다.각 스레드는 개별적으로 동작합니다.PARTITIONs
테이블로 이동합니다.모든 배팅은 평가 순서대로 취소됩니다.
'이것'이 구현되면 분할되지 않은 데이터라도 분할하는 것은 어떨까요?SELECT
행성성 ?기 ?? ????
넌 논쟁에서 이길 수 없을 거야.
네, 오랫동안 "추천된" 상태를 유지할 수 있습니다....sql_mode
오래된 방식으로 쿼리를 실행합니다.또는 @variables의 존재는 (예측 가능성을 위해) 특정 최적화를 억제합니다. 등등
bugs.mysql.com에서 보고 싶은 내용을 기재한 '요청서'를 작성해 주실 것을 제안합니다(mariadb.com에서도 할 수 있지만, 전자를 보고 있습니다).
언급URL : https://stackoverflow.com/questions/56939034/order-of-variable-assignment-evaluation-in-select-can-differ-from-order-of-rows
'programing' 카테고리의 다른 글
Java에서 LRU 캐시를 구현하려면 어떻게 해야 합니까? (0) | 2023.01.20 |
---|---|
라디오 버튼을 끄려면 어떻게 해야 하나요? (0) | 2023.01.20 |
요소에 JavaScript의 클래스가 포함되어 있는지 확인하시겠습니까? (0) | 2023.01.20 |
python을 사용하여 단순 XML 파일 만들기 (0) | 2023.01.20 |
PHP의 Date Time 클래스에서 Date Time-> date에 액세스할 수 없는 이유는 무엇입니까? (0) | 2023.01.20 |