LIKE 문자 길이 제한 극복


13

여기서 LIKE 문자 길이 제한 을 읽으면 LIKE 절에서 ~ 4000 자보다 긴 텍스트를 보낼 수없는 것 같습니다.

특정 쿼리에 대한 쿼리 계획 캐시에서 쿼리 계획을 가져 오려고합니다.

SELECT *
FROM sys.dm_exec_cached_plans AS cp 
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp 
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
where st.text like '%MY_QUERY_LONGER_THAN_4000_CHARS%' ESCAPE '?'

내부의 쿼리 LIKE가 4000 자보다 길면 쿼리가 캐시 계획에 있더라도 결과가 0입니다. (나는 적어도 오류를 기대하고 있었다).

이 문제를 해결하거나 다르게 수행 할 수있는 방법이 있습니까? > 10000문자 길이 가 될 수있는 쿼리가 있고로 찾을 수없는 것처럼 보입니다 LIKE.


2
텍스트를 where st.text like '%MY_QUERY%CHARS%' ESCAPE '?'
세분화하십시오

4
실제로 4,000 자에 대해 동일하지만 다른 쿼리 텍스트가 있습니까?
Martin Smith

@MartinSmith 예, 그런 쿼리가 있습니다.
Dan Dinu

답변:


9

이 이후 순수 T-SQL에서 해결 될 수있는 표시도하지 CHARINDEX않고 PATINDEX문자열 "검색하기"(8000, 즉 최대에 8000 개 이상의 바이트를 사용하여 허용 VARCHAR또는 4000 NVARCHAR자). 이것은 다음 테스트에서 볼 수 있습니다.

SELECT 1 WHERE CHARINDEX(N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 7000),
                         N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 6000)) > 0

SELECT 1 WHERE PATINDEX(N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 7000),
                        N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 6000)) > 0

두 쿼리 모두 다음 오류를 반환합니다.

메시지 8152, 수준 16, 상태 10, 줄 xxxxx
문자열 또는 이진 데이터가 잘립니다.

그리고 7000이러한 쿼리 중 하나를 줄이면 3999오류가 제거됩니다. 4000두 경우 모두 의 값은 N'Z'시작 부분 의 추가 문자 로 인해 오류도 발생 합니다.

그러나 이는 SQLCLR을 사용하여 수행 할 수 있습니다. 유형의 두 개의 입력 매개 변수를 허용하는 스칼라 함수를 작성하는 것은 매우 간단합니다 NVARCHAR(MAX).

다음 예제는 SQL # SQLCLR 라이브러리 의 무료 버전을 사용하여이 기능을 보여줍니다 (제작했지만 String_Contains 는 무료 버전에서 다시 사용할 수 있습니다 :-).

설정

-- DROP TABLE #ContainsData;
CREATE TABLE #ContainsData
(
  ContainsDataID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  Col1 NVARCHAR(MAX) NOT NULL
);

INSERT INTO #ContainsData ([Col1])
VALUES (N'Q' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 15000)),
       (N'W' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 20000)),
       (N'Z' + REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 70000));

-- verify the lengths being over 8000
SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM   #ContainsData tmp;

테스트

SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM   #ContainsData tmp
WHERE  SQL#.String_Contains(tmp.[Col1], REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 15100)) = 1;
-- IDs returned: 2 and 3

SELECT tmp.[ContainsDataID], tmp.[Col1], DATALENGTH(tmp.[Col1])
FROM   #ContainsData tmp
WHERE  SQL#.String_Contains(tmp.[Col1], REPLICATE(CONVERT(NVARCHAR(MAX), N'a'), 26100)) = 1;
-- IDs returned: 3

것을 명심하시기 바랍니다 String_Contains가 모든 민감한 (케이스, 악센트, 가나 및 폭) 비교를 사용하고 있습니다.


2

대체 접근 방식도 요청 했으므로 특정 계획을 찾는 다른 방법 plan_hash은 다음과 같이 쿼리를 변경하여 계획을 검색하는 것입니다 .

SELECT *
FROM sys.dm_exec_cached_plans AS cp 
INNER JOIN sys.dm_exec_query_stats qs
    ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp 
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
WHERE qs.query_hash = 0xE4026347B5F49802

내가 찾은 QueryHash값 을 얻는 가장 빠른 방법 은 문제의 쿼리를 쿼리 창에 붙여 넣은 다음 예상 실행 계획을 표시하는 것입니다. XML 출력을 읽고 요소 에서 QueryHash속성을 찾으면 StmtSimple필요한 것을 얻을 수 있습니다. QueryHash 값을 위의 쿼리에 연결하면 원하는 것을 얻을 수 있습니다.

QueryHash잘못 설명했을 때 신속하게 가치를 얻는 방법을 보여주는 스크린 샷 이 있습니다.

예상 실행 계획 표시

여기에 이미지 설명을 입력하십시오

실행 계획 XM 표시 ...

여기에 이미지 설명을 입력하십시오

QueryHash 값 검색

여기에 이미지 설명을 입력하십시오

찾고있는 쿼리가 Estimated Execution Plan을 표시하는 쿼리와 다른 경우 트릭이 작동하지 않지만 CLR 루틴과 함께 제공되는 모든 뉘앙스보다 빠르면 제대로 작동합니다.


0

쿼리 텍스트에 액세스 할 수있는 경우 (텍스트를 수정할 수 있음) 원하는 주석에 고유 한 주석을 추가 할 수 있습니다.

select /* myUniqueQuery123 */ whatever from somewhere ...

그런 다음 myUniqueQuery123전체 쿼리 텍스트 대신 계획 캐시에서 검색 하십시오.

... where st.text like '%myUniqueQuery123%'

추신. 검증되지 않은

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.