'팁&테크/MSSQL'에 해당되는 글 15건

  1. 2022.11.17 [MSSQL] 쿼리를 병렬 처리하게 하는 방법
  2. 2022.10.06 procedure/function/trigger 의 내용 찾기
  3. 2020.06.29 MERGE Statement
  4. 2020.06.22 캐싱된 plain 에서 Missing index 쿼리 확인
  5. 2020.01.23 [MSSQL] COLLATE 대소문자 구분
  6. 2019.11.29 [MSSQL] GeoLocation 범위계산
  7. 2019.11.04 [MSSQL] IDENTITY Column (PK)의 값을 insert 하기
  8. 2019.09.19 [MSSQL] 현재의 Isolation Level 확인
  9. 2019.04.30 [MSSQL] rows to columns (PIVOT)
  10. 2019.04.30 INSERTED PK 얻는 방법(SCOPE_IDENTITY, OUTPUT, MERGE INTO)
2022. 11. 17. 13:56

[MSSQL] 쿼리를 병렬 처리하게 하는 방법

쿼리 옵티마이저가 알아서 하겠지만 강제로 병렬 처리 하게 하는 방법은 아래 와 같다.

 

2016 이상

1
2
3
4
5
6
SELECT *
FROM [Sales].[Orders] t
WHERE t.CustomerID >100
ORDER BY OrderID
OPTION(USE HINT('ENABLE_PARALLEL_PLAN_PREFERENCE'))
GO

 

이전 버전

1
2
3
4
5
6
SELECT *
FROM [Sales].[Orders] t
WHERE t.CustomerID >100
ORDER BY OrderID
OPTION(QUERYTRACEON 8649)
GO
2022. 10. 6. 10:58

procedure/function/trigger 의 내용 찾기

일반 적인 문자열

SELECT DISTINCT
       o.name AS Object_Name,
       o.type_desc
FROM sys.sql_modules m
       INNER JOIN
       sys.objects o
         ON m.object_id = o.object_id
WHERE m.definition Like '%totalRevenue%'

ESACPE 처리 해야 하는 문자열

SELECT DISTINCT
       o.name AS Object_Name,
       o.type_desc
FROM sys.sql_modules m
       INNER JOIN
       sys.objects o
         ON m.object_id = o.object_id
WHERE m.definition Like '%\[totalRevenue\]%' ESCAPE '\'
2020. 6. 29. 08:07

MERGE Statement

WITH TARGET
AS (
SELECT Col FROM TargetTable WHERE Condition = :Condition
)
MERGE INTO TARGET
USING (
SELECT Col FROM SourceTable WHERE Condition = :Condition
) SOURCE ON TARGET.Col = SOURCE.Col
WHEN NOT MATCHED THEN
INSERT (Col) VALUES (Col)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT $ACTION , INSERTED.*, DELETED.*;

1. SOURCE 테이블과 TARGET 테이블을 비교해서 TARGET 테이블에 INSERT, UPDATE, DELETE 문을 수행.

[INTO] 생략가능


2. SOURCE 테이블에 조건이 필요할 경우 서브쿼리 사용.


3. TARGET 테이블에 조건이 필요할 경우 WITH 문 사용.


4. WHEN MATCHED THEN

ON 절의 조건 컬럼이 SOURCE, TARGET 양쪽다 존재하는 경우 실행

보통 UPDATE 구분 사용


5. WHEN NOT MATCHED BY TARGET THEN

ON 절의 조건 컬럼이 SOURCE에는 있는데 TARGET 에 없는 경우 실행

보통 INSERT 구문 사용(INSERT TARGET)

[BY TARGET] 생략가능


6. WHEN NOT MATCHED BY SOURCE THEN

ON 절의 조건 컬럼이 TARGET에는 있는데  SOURCE에 없는 경우 실행

보통 DELETE 구문 사용(DELETE TARGET)

2020. 6. 22. 12:05

캐싱된 plain 에서 Missing index 쿼리 확인

with XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql)
SELECT --TOP 10
db_name
,sp_name
,sp_text
,[statement_text]
,X.*
,[creation_time]
,[ExecutionCount]
FROM
(
SELECT
db_name(qt.dbid) AS 'db_name'
,qt.text AS 'sp_text'
, substring(qt.text, (qs.statement_start_offset/2)+1
, ((case qs.statement_end_offset
when -1 then datalength(qt.text)
else qs.statement_end_offset
end - qs.statement_start_offset)/2) + 1) as statement_text
, qs.creation_time
, qs.execution_count AS 'ExecutionCount'
, cast(qp.query_plan as xml) as query_plan
,OBJECT_NAME(qp.objectid,qp.dbid) as sp_name
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle,qs.statement_start_offset,qs.statement_end_offset) qp
) Y
CROSS APPLY
(
SELECT
c.value('(./@Impact)[1]','float') as missing_index_Impact
,c.value('(./sql:MissingIndex/@Database)[1]','varchar(100)') + '.'+
c.value('(./sql:MissingIndex/@Schema)[1]','varchar(100)') + '.'+
c.value('(./sql:MissingIndex/@Table)[1]','varchar(100)') as [missing_index_Table]
FROM Y.query_plan.nodes('//sql:MissingIndexGroup')B(C)
) X


2020. 1. 23. 10:15

[MSSQL] COLLATE 대소문자 구분

COLLATE 절은 char, varchar, text, nchar, nvarcharntext 데이터 형식에만 적용할 수 있습니다.

where 조건에서 적용

-- 대소문자 구문(영어/미국)
SELECT TOP(1) * FROM tblUsers WHERE username = ? COLLATE SQL_Latin1_General_CP1_CS_AS
-- 대소문자 구분안함(영어/미국)
SELECT TOP(1) * FROM tblUsers WHERE username = ? COLLATE SQL_Latin1_General_CP1_CI_AS

table 생성시에 설정하거나 alter table로 변경

ALTER TABLE Table1
ALTER COLUMN Column1 VARCHAR(200)
COLLATE SQL_Latin1_General_CP1_CS_AS -- 대소문자 구분(영어/미국)

ALTER TABLE Table1
ALTER COLUMN Column1 VARCHAR(200)
COLLATE SQL_Latin1_General_CP1_CI_AS -- 대소문자 구분안함(영어/미국)

사용가능한 Collation 명칭 참고

COLLATE SQL_Latin1_General_CP1_CS_AS

Codepage 데이터 정렬에 사용되는 코드 페이지를 표시하는 1~4자리 숫자를 지정합니다. CP1은 코드 페이지 1252를 지정하며 다른 모든 코드 페이지에 대해서는 완전한 코드 페이지 번호를 지정합니다. 예를 들어 CP1251은 코드 페이지 1251을 지정하며 CP850은 코드 페이지 850을 지정합니다.

CaseSensitivity CI는 대/소문자를 구분하지 않도록 지정하고 CS는 대/소문자를 구분하도록 지정합니다.

AccentSensitivity AI는 악센트를 구분하지 않도록 지정하고 AS는 악센트를 구분하도록 지정합니다.

BIN 사용할 이진 정렬 순서를 지정합니다.


사용가능한 Collation 확인
SELECT name, description FROM fn_helpcollations()

SQL_Latin1_General_CP1_CS_AS is the default collation for the English (United States) locale
SQL_Latin1_General_CS_AS is the default collation for any other English locale, such as English (United Kingdom)

2019. 11. 29. 15:05

[MSSQL] GeoLocation 범위계산

alter table [yourTable] add [p] as geography::Point(Latitude, Longitude, 4326) persisted;
create spatial index [yourSpatialIndex] on [yourTable] ([p])

declare @Latitude float = <somevalue>, @Longitude float = <somevalue>;
declare @point geography = geography::Point(@Latitude, @Longitude, 4326);
declare @distance int = <distance in meters>;

select * from [yourTable] where @point.STDistance([p]) <= @distance;


2019. 11. 4. 08:45

[MSSQL] IDENTITY Column (PK)의 값을 insert 하기

Identity로 설정된 column의 값은 임의로 변경하지 못함.

자동으로 증가되는 값 이외의 수치로 변경(0, -1등등)하기 위해서는 IDENTITY_INSERT를 변경해 주어야 함.

update는 delete 후 insert 하는 수 밖에 없음

SET IDENTITY_INSERT [table] ON
INSERT INTO [table] (PK) VALUES (-1)
SET IDENTITY_INSERT [table] OFF

 

2019. 9. 19. 12:44

[MSSQL] 현재의 Isolation Level 확인

SELECT
CASE transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncommitted'
WHEN 2 THEN 'ReadCommitted'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END AS TRANSACTION_ISOLATION_LEVEL
FROM sys.dm_exec_sessions
WHERE session_id = @@SPID


2019. 4. 30. 09:56

[MSSQL] rows to columns (PIVOT)

아래 형태의 rows 를 columns 로 변환하는 방법

주의) subquery 의 select column에 따라서 최종 row수가 변할 수 있으니 사용하지 않더라도 subquery에서는 결과 row를 구분 할 수 있는 column(like pk)을 포함시켜야 함


TABLE2

Identifier | Content

Identifier_Name1 | blabla

Identifier_Name2 | blablabla

Identifier_Name3 | blablabla..

SELECT P.[Identifier_Name1], P.[Identifier_Name2], P.[Identifier_Name3]
FROM (
SELECT [PK_NAME], [Identifier], [Content]
FROM [TABLE2]
WHERE [TABLE2].[COLUMN] = ?
) A
PIVOT (
MAX(A.[Content]) FOR A.[Identifier] IN (
[Identifier_Name1],
[Identifier_Name2],
[Identifier_Name3]
)
) P


다른 table과 join 하여 하나의 row로 표시하는 법

SELECT P.[TABLE1_COLUMN], P.[Identifier_Name1], P.[Identifier_Name2], P.[Identifier_Name3]
FROM (
SELECT
[TABLE1].[KEY],
[TABLE1].[COLUMN],
[TABLE2].[Identifier], [TABLE2].[Content]
FROM [TABLE1]
LEFT JOIN [TABLE2] ON [TABLE1].[KEY] = [TABLE2].[KEY]
WHERE [TABLE1].[COLUMN] = ?
) A
PIVOT (
MAX(A.[Content]) FOR A.[Identifier] IN (
[Identifier_Name1],
[Identifier_Name2],
[Identifier_Name3]
)
) P


반대개념으론로는 UNPIVOT이 있음


2019. 4. 30. 09:37

INSERTED PK 얻는 방법(SCOPE_IDENTITY, OUTPUT, MERGE INTO)

1. SCOPE_IDENTITY() 사용

INSERT INTO [TABLE] ([COLUMN]) VALUE ('value')
SELECT SCOPE_IDENTITY() AS pk


2. OUTPUT 사용

INSERT INTO [TABLE] ([COLUMN])
OUTPUT INSERTED.[PK_COLUMN]
SELECT 'value' FROM [TABLE2] -- 그냥 insert 도 되고 insert select 도 사용 가능


3. INSERT 된 PK와 기존PK 얻는 방법(MERGE INTO 사용)

MERGE INTO [TARGET_TABLE] TT
USING (
SELECT [PK_NAME], [COLUMN] FROM [SOURCE_TABLE] WHERE [COLUMN] = ?
) ST ON TT.[PK_COLUMN] = ST.[PK_COLUMN]
WHEN NOT MATCHED THEN
INSERT ([TT_COLUMN]) VALUES (ST.[COLUMN])
OUTPUT INSERTED.[TT_PK_NAME] AS NewPK, ST.[PK_NAME] AS OldPK;