디비 서버를 관리하다 보면 여러 서버들에 일괄적으로 쿼리를 수행할 할 일이 생기곤 한다

SSMS의 등록된 서버로 그룹 서버 전체에 명령어를 날일 수도 있지만

각 서버들에 아주 약간씩 다른녀석들이 있다면 이야기가 달라진다. (예를들어 DB명이나 하드코딩 같은...)


동적 쿼리를 생성하여 실행하는 EXEC나 sq_executesql 프로시저를 이용 할 수 도 있겠지만

장문의 프로시저를 동시에 생성하는 일은 문자열 길이를 초과해 버리면 곤란한 일일 수 밖에 없다.


이럴때 개인적으로 쓰는 방법은 SQLCmd를 활용하는 방법이다.

보안 규정에 따라 삭제하는 경우도 있는데 애석하게도 그런 경우엔 다른 방법을 찾아보는것이 좋겠다.



SQLCmd의 옵션을 살펴보자


디비서버에 접속하는 방법은 각각의 환경마다 다르니 생략하고 디비가 설치된 서버에서 직접 실행하며

윈도우 인증을 사용한다면 -E옵션은 복잡한 Connection String을 작성할 일을 해결해 준다.


여기서 주목해야 할 옵션은 -q, -Q, -i, -o 옵션이다.


IT를 한다는 사람이라면 너무나 친숙한 "Hello SQL"를 찍어보자


입력한 쿼리의 결과가 콘솔창에 뿌려진다

(만약 컬럼이 많다면 putty같은 프로그램으로 tenet접속을 해서 실행시킨것이 아닌 이상 감당할 수 없는 데이터를 받게 될 것이다.)

그렇다면 PRINT문은 어떻게 나올까?


SSMS상에서는 다른 탭으로 결과와 메시지로 구분되던 데이터가 함께 나온다.

하지만 이래서는 다른 사람에게 결과를 전달 할 수 없다.

다음과 같이 파일로 만들어 보자.


명령어를 수행한 결과가 텍스트로 떨어졌다.

명령어가 매번 간단하다고 보장 할 수 없다.

파일로 입력해보자.


역시 잘 작동 된다.

이미 눈치 챈 사람이 많을 것이다 왜 자꾸 수행 결과를 보여주는지 파일로 떨구는지 파일로 입력 받았는지...

다음과 같이 결과를 다시 입력으로 할 수도 있다.



위와 같이 프로시저 조자도 생성이 가능하다.

문자열을 조작하여 만드는것은 쉬운 일이니 서버마다 서버에 있는 값으로 하드 코딩된 나쁜 프로시저를 생성해야만 하는 일이 생긴다면 사용해 볼 수 있는 무기가 우리에게 생겼다



MySQL이나 Oracle의 경우 에초에 콘솔 기반이라 저런 꼼수를 많이 썻었지만

MSSQL은 기본으로 너무 좋은 GUI 툴을 주기 때문에 저런 꼼수를 쓸 생각을 못했으나 필요에 의해 사용할 일이 있어

찾아서 정리해 본다.




ps. 혹시 각 서버에 접속해서 일일이 실행하진 않을거라 믿는다.

중앙에서 각 서버에 접속 할 수 있는 곳이 있다면 배치 파일로(혹은 파워쉘로) 쉽게 일괄 실행을 할 수 있을 것이다.


ps2. PRINT 문장을 언제 일일이 써주냐는 사람이 있다면 열 편집이 가능한 텍스트 에디터를 사용해 보길 바란다.

(찾아보면 유용한 무료 텍스트 에디터가 많다.)

몇만라인의 프로시저라 해도(그런게 있으려나;) 약간의 머리와 몇초 정도면 저런 구문으로 만들 수 있다.


Posted by Mr.Jo :

Identity 가 지정되어있는 컬럼에 임의의 값을 넣으려고 하면 에러가 나면서 넣어지지 않는다



임의의 값을 넣기 위해선 다음과 같이 명시한다면 입력이 가능하다

SET IDENTITY_INSERT [대상 테이블] ON;


입력을 위해서는 INSERT절에 해당 컬럼을 명시적으로 선언해야 한다

INSERT INTO [대상 테이블]([컬럼2], [컬럼2], [컬럼3], [컬럼4]...)
VALUES([값1], [값2], [값3], [값4]...);

INSERT INTO [대상 테이블]([컬럼2], [컬럼2], [컬럼3], [컬럼4]...)
SELECT [값1], [값2], [값3], [값4]... FROM ...;


입력 후에 다음과 같이 만들어 준다.

SET IDENTITY_INSERT [대상 테이블] OFF;

※주의사항 : 한번에 한 테이블에만 설정이 가능 하기 때문에 여러 테이블 대상일 경우 하나씩 설정 해야 함

Posted by Mr.Jo :

프로시저를 작성하다가 인자로 들어오는 스트링에 특수 문자 유무 혹은 형식에 맞추어 입력했는지 검사 할 필요가 있는데 MSSQL의 경우 제약이 조금 있기는 하지만 정규식을 사용 할 수가 있다



DECLARE @String varchar(1000);
SET @String = 'string';

IF @String Like '%[^-_.a-z0-9]%'
    PRINT '특수문자가 있음';
ELSE
    PRINT '특수문자가 없음';


Posted by Mr.Jo :

작동버젼 : MSSQL 2000 이상
사용방법 : []안의 내용 수정 후 사용
주의사항 : 만일의 경우를 위하여 테이블을 SELECT INTO 등으로 백업 후 사용하며
               IDENTITY컬럼이 이미 있는 경우 임시 테이블에 값을 넣어 처리 후 대체
설      명 : 중복되는 ROW중 IDENTITY컬럼값이 가장 작은 녀석만 남고 삭제 하는 쿼리기 때문에
               원하는 순서로 정렬된 Identity 컬럼 추가 을 참조하여 남아야 할 키 값의 IDENTITY값을 가장 작게 만들것!



DECLARE @TableName sysname
DECLARE @KeyColumns varchar(256)

SET @TableName = '[테이블명]';
SET @KeyColumns = '[기본키컬럼명1],[기본키컬럼명2],[기본키컬럼명3]';


DECLARE @Query nvarchar(4000);

SET @Query = N'ALTER TABLE ' + @TableName + ' ADD TempKeyColumn int IDENTITY(1,1)';
EXECUTE sp_executesql @Query;

SET @Query = N'DELETE ' + @TableName + ' WHERE TempKeyColumn NOT IN (SELECT MIN(TempKeyColumn) AS TempKeyColumn FROM ' + @TableName + ' GROUP BY ' + @KeyColumns + ')';
EXECUTE sp_executesql @Query;


SET @Query=N'ALTER TABLE ' + @TableName + ' DROP COLUMN TempKeyColumn;';
EXECUTE sp_executesql @Query;

GO


Posted by Mr.Jo :

작동버젼 : MSSQL 2000 및 2005 이상
사용방법 : "[]"안의 내용 변경 후 사용
주의사항 : 이름 확인
설      명 : 다른서버에서 데이터 베이스 복원 시 디비의 유저와 서버의 로그인 사이에 SPID가 맞지 않아서
              로그인이 되지 않을 수 있는데 에초에 로그인 생성 시 SPID를 지정하여 생성하거나
              다음과 같은 방법으로 해결 할 수 있음



MSSQL 2000의 경우

use [데이터 베이스명];
GO

EXECUTE sp_change_users_login 'Auto_Fix','[로그인명]';
GO


MSSQL 2005 이상의 경우

USE [데이터 베이스명];
GO

ALTER USER [유저명]WITH LOGIN = [로그인명];
GO

MSSQL 2005 이상 모든 디비, 모든 유저에 적용

DECLARE @Query nvarchar(4000);
DECLARE QueryCursor CURSOR FOR
	SELECT 'ALTER USER ' + a.name + ' WITH LOGIN = ' + b.name AS Query
	FROM sys.database_principals AS a WITH(NOLOCK)
	INNER JOIN sys.sql_logins  AS b WITH(NOLOCK) ON a.name = b.name
	WHERE a.type IN ('S', 'U')
	  AND b.type IN ('S', 'U');

OPEN QueryCursor;

FETCH QueryCursor INTO @Query;

WHILE @@FETCH_STATUS = 0
BEGIN
	PRINT @Query;
	EXECUTE sp_executesql @Query;
	FETCH QueryCursor INTO @Query;
END;

CLOSE QueryCursor;
DEALLOCATE QueryCursor;
GO


Posted by Mr.Jo :

작동버젼 : MSSQL 2000 이상
사용방법 : [로그인명] 수정 후
주의사항 : Kill해서는 안되는 접속이 있지 않은지 확인 필요
설      명 : 직접 사용 보다는 응용하여 사용하는 경우가 더 많음



USE master;
GO

DECLARE @LoginName nvarchar(218);
SET @LoginName = '[로그인명]';



DECLARE @Query nvarchar(4000);
DECLARE @SPID int;

DECLARE Kill_Cursor CURSOR FOR
	SELECT SPID
	FROM  master.dbo.sysprocesses
	WHERE SPID <> @@SPID
	  AND loginame = @LoginName;

OPEN Kill_Cursor;

FETCH Kill_Cursor INTO @SPID;
WHILE @@FETCH_STATUS = 0
BEGIN
	SET @Query = 'KILL ' + CONVERT(varchar, @SPID) + ';';
	PRINT @Query;
	EXECUTE sp_executesql @Query;
	FETCH Kill_Cursor INTO @SPID;
END;

CLOSE Kill_Cursor;
DEALLOCATE Kill_Cursor;
GO


Posted by Mr.Jo :

작동버젼 : SQL Sserver 2005 이상
사용방법 : Edit Here 라고 표기되어 있는 곳 수정(타겟 DB명, 변경하고자 하는 Collation명으로 변경)
주의사항 : 여러 Collation이 존재해야 하는 DB에서는 사용하지 말것!
설      명 : DBMS의 Collation이 잘못 설치된 상태에서 디비 생성이 됬을 경우
               명시적으로 생성하지 않았다면 테이블의 char, varchar컬럼등도 변경이 필요 하기에 만든 스크립트
               전 영역 변경이 필요하지 않을 경우 스크립트 만 추출하여 실행 할 수 있음



--Edit Here
USE [YourDB];
GO

SET NOCOUNT ON;


IF OBJECT_ID('tempdb.dbo.#AlterCollateQuery', 'U') IS NOT NULL
	DROP TABLE #AlterCollateQuery;
GO

CREATE TABLE #AlterCollateQuery
(
	 ExecuteOrder int identity(1,1)
	,Query nvarchar(4000)
)
GO

IF OBJECT_ID('dbo.F_GetForeignKeyColumns', 'FN') IS NOT NULL
	DROP FUNCTION dbo.F_GetForeignKeyColumns;
GO

CREATE FUNCTION dbo.F_GetForeignKeyColumns
(
	 @object_id	int
)
RETURNS varchar(4000)
AS
BEGIN
	DECLARE @return				varchar(4000);
	DECLARE @referenced_object_id	int;
	DECLARE @parent_columns		varchar(4000);
	DECLARE @referenced_columns	varchar(4000);
	
	SET @parent_columns = '';
	SET @referenced_columns = '';

	SELECT
		 @referenced_object_id = a.referenced_object_id
		,@parent_columns = @parent_columns + N', [' + b.name + N']'
		,@referenced_columns = @referenced_columns + N', [' + c.name + N']'
	FROM sys.foreign_key_columns AS a
		INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
		INNER JOIN sys.columns AS c ON c.object_id = a.referenced_object_id AND c.column_id = a.referenced_column_id
	WHERE a.constraint_object_id = @object_id;
	
	SELECT @return = N'FOREIGN KEY(' + STUFF(@parent_columns, 1, 2, N'') + N') REFERENCES [' + a.name + N'].[' + b.name + N'](' + STUFF(@referenced_columns, 1, 2, N'') + N')'
	FROM sys.schemas AS a
		INNER JOIN sys.tables  AS b ON a.schema_id = b.schema_id
	WHERE b.object_id = @referenced_object_id;
	
	RETURN @return;
END;
GO



IF OBJECT_ID('dbo.F_GetIndexColumns', 'FN') IS NOT NULL
	DROP FUNCTION dbo.F_GetIndexColumns;
GO

CREATE FUNCTION dbo.F_GetIndexColumns
(
	 @object_id	int
	,@index_id	int
)
RETURNS varchar(4000)
AS
BEGIN
	DECLARE @Return nvarchar(4000);
	SET @Return = '';
	
	SELECT @Return = @Return + N', [' + b.name + N'] ' + CASE WHEN a.is_descending_key = 0 THEN N'ASC' ELSE N'DESC' END
	FROM sys.index_columns AS a
		INNER JOIN sys.columns AS b ON a.object_id = b.object_id AND a.column_id = b.column_id
	WHERE a.object_id = @object_id
	  AND a.index_id = @index_id
	ORDER BY a.index_column_id;
	
	RETURN STUFF(@Return, 1, 2, '');
END;
GO

IF OBJECT_ID('tempdb.dbo.#QueryList', 'U') IS NOT NULL
	DROP TABLE #QueryList;
GO

CREATE TABLE #QueryList
(
	 executeDropOrder int
	,dropQuery nvarchar(4000)
	,executeCreateOrder int
	,createQuery nvarchar(4000)
);
GO




DECLARE @collation_name varchar(4000);
--Edit Here
SET @collation_name = N'Korean_Wansung_CI_AS';




INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
	 1 AS executeDropOrder
	,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] DROP CONSTRAINT [' + a.name + N'];' AS DropDF
	,4 AS executeDropOrder
	,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] ADD CONSTRAINT [' + a.name + N'] DEFAULT' + a.definition + N' FOR [' + b.name + N'];' AS CreateDF
FROM sys.default_constraints AS a
	INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
	INNER JOIN sys.tables AS c ON b.object_id = c.object_id
	INNER JOIN sys.schemas AS d ON c.schema_id = d.schema_id;


INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
	 2 AS executeDropOrder
	,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] DROP CONSTRAINT [' + a.name + N'];' AS DropCK
	,3 AS executeDropOrder
	,N'ALTER TABLE [' + d.name + N'].[' + c.name + N'] ADD CONSTRAINT [' + a.name + N'] CHECK' + a.definition + CASE WHEN a.is_not_for_replication = 1 THEN ' NOT FOR REPLICATION' ELSE '' END + N';' AS CreateCK
FROM sys.check_constraints AS a
	INNER JOIN sys.columns AS b ON b.object_id = a.parent_object_id AND b.column_id = a.parent_column_id
	INNER JOIN sys.tables AS c ON b.object_id = c.object_id
	INNER JOIN sys.schemas AS d ON c.schema_id = d.schema_id;


INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT
	 3 AS executeDropOrder
	,N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] DROP CONSTRAINT [' + c.name + N'];' AS DropFK
	,2 AS executeDropOrder
	,N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] ADD CONSTRAINT [' + c.name + N'] ' + dbo.F_GetForeignKeyColumns(c.object_id) + CASE WHEN c.delete_referential_action_desc = 'NO_ACTION' THEN '' ELSE ' ON DELETE ' + c.delete_referential_action_desc END + CASE WHEN c.update_referential_action_desc = 'NO_ACTION' THEN '' ELSE ' ON UPDATE ' + c.update_referential_action_desc END + CASE WHEN c.is_not_for_replication = 1 THEN ' NOT FOR REPLICATION' ELSE '' END + N';' COLLATE Latin1_General_CI_AS_KS_WS AS CreateFK
FROM sys.schemas AS a
	INNER JOIN sys.tables AS b ON a.schema_id = b.schema_id
	INNER JOIN sys.foreign_keys AS c ON b.object_id = c.parent_object_id
WHERE EXISTS(SELECT TOP 1 '' FROM sys.foreign_key_columns AS d INNER JOIN sys.columns AS e ON d.parent_object_id = e.object_id AND d.parent_column_id = e.column_id WHERE e.collation_name <> @collation_name)
  AND EXISTS(SELECT TOP 1 '' FROM sys.foreign_key_columns AS d INNER JOIN sys.columns AS e ON d.referenced_object_id = e.object_id AND d.referenced_column_id = e.column_id WHERE e.collation_name <> @collation_name);


INSERT INTO #QueryList(executeDropOrder, dropQuery, executeCreateOrder, createQuery)
SELECT DISTINCT
	 4 AS executeDropOrder
	,CASE
		WHEN d.is_primary_key = 0 AND d.is_unique_constraint = 0 THEN N'DROP INDEX [' + d.name + N'] ON [' + f.name + N'].[' + a.name + N'];'
		ELSE N'ALTER TABLE [' + f.name + N'].[' + a.name + N'] DROP CONSTRAINT [' + d.name + N'];'
	END AS DropIndex
	,1 AS executeDropOrder
	,CASE
		WHEN d.is_primary_key = 0 AND d.is_unique_constraint = 0 THEN N'CREATE ' + CASE WHEN d.is_unique = 1 THEN N'UNIQUE ' ELSE '' END + d.type_desc + ' INDEX [' + d.name + N'] ON [' + f.name + N'].[' + a.name + N'](' + dbo.F_GetIndexColumns(d.object_id, d.index_id) + N')' + CASE WHEN d.fill_factor > 0 THEN N' WITH FILLFACTOR = ' + CONVERT(varchar, d.fill_factor) ELSE N'' END + N' ON [' + e.name + N'];'
		ELSE N'ALTER TABLE [' + f.name + N'].[' + a.name + N'] ADD CONSTRAINT [' + d.name + N'] ' + CASE WHEN d.is_primary_key = 1 THEN N'PRIMARY KEY ' WHEN d.is_unique_constraint = 1 THEN N'UNIQUE ' END + d.type_desc + N'(' + dbo.F_GetIndexColumns(d.object_id, d.index_id) + N')' + CASE WHEN d.fill_factor > 0 THEN N' WITH FILLFACTOR = ' + CONVERT(varchar, d.fill_factor) ELSE N'' END + N' ON [' + e.name + N'];'
	END COLLATE Latin1_General_CI_AS_KS_WS AS CreateIndex
FROM sys.tables AS a
	INNER JOIN sys.columns AS b ON a.object_id = b.object_id
	INNER JOIN sys.index_columns AS c ON b.column_id = c.column_id AND b.object_id = c.object_id
	INNER JOIN sys.indexes AS d ON c.object_id = d.object_id AND c.index_id = d.index_id
	INNER JOIN sys.data_spaces AS e ON d.data_space_id = e.data_space_id
	INNER JOIN sys.schemas AS f ON a.schema_id = f.schema_id;






INSERT INTO #AlterCollateQuery(Query)
SELECT dropQuery
FROM #QueryList
ORDER BY executeDropOrder;

INSERT INTO #AlterCollateQuery(Query)
SELECT N'ALTER TABLE [' + a.name + N'].[' + b.name + N'] ALTER COLUMN [' + c.name + N'] ' + d.name + N'(' + CASE WHEN c.max_length < 1 OR c.max_length > 4000 THEN 'MAX' ELSE CONVERT(varchar, c.max_length) END + N') COLLATE ' + @collation_name + CASE WHEN c.is_nullable = 0 THEN N' NOT NULL' ELSE N' NULL' END + N';'
FROM sys.schemas AS a
	INNER JOIN sys.tables AS b ON a.schema_id = b.schema_id
	INNER JOIN sys.columns AS c ON c.object_id = b.object_id
	INNER JOIN sys.types AS d ON d.user_type_id = c.user_type_id
WHERE c.collation_name <> @collation_name;


INSERT INTO #AlterCollateQuery(Query)
SELECT a.Query
FROM
	(
		SELECT N'ALTER DATABASE ' + DB_NAME() + N' SET SINGLE_USER WITH ROLLBACK IMMEDIATE;' AS Query
		UNION ALL SELECT N'ALTER DATABASE ' + DB_NAME() + N' COLLATE ' + @collation_name + ';' AS Query
		UNION ALL SELECT N'ALTER DATABASE ' + DB_NAME() + N' SET MULTI_USER;' AS Query
	) AS a
WHERE EXISTS(SELECT TOP 1 '' FROM sys.databases WHERE name = DB_NAME() AND collation_name <> @collation_name);

INSERT INTO #AlterCollateQuery(Query)
SELECT createQuery
FROM #QueryList
ORDER BY executeCreateOrder;
GO



IF OBJECT_ID('dbo.F_GetForeignKeyColumns', 'FN') IS NOT NULL
	DROP FUNCTION dbo.F_GetForeignKeyColumns;
GO

IF OBJECT_ID('dbo.F_GetIndexColumns', 'FN') IS NOT NULL
	DROP FUNCTION dbo.F_GetIndexColumns;
GO

IF OBJECT_ID('tempdb.dbo.#QueryList', 'U') IS NOT NULL
	DROP TABLE #QueryList;
GO


DECLARE @Query nvarchar(4000);
DECLARE Collate_Query CURSOR FOR
	SELECT a.Query
	FROM #AlterCollateQuery AS a WITH(NOLOCK)
	ORDER BY a.ExecuteOrder;

OPEN Collate_Query;

FETCH Collate_Query INTO @Query;

WHILE @@FETCH_STATUS = 0
BEGIN
	PRINT @Query;
	EXECUTE sp_executesql @Query;
	
	FETCH Collate_Query INTO @Query;
END;

CLOSE Collate_Query;
DEALLOCATE Collate_Query;
GO


IF OBJECT_ID('tempdb.dbo.#AlterCollateQuery', 'U') IS NOT NULL
	DROP TABLE #AlterCollateQuery;
GO


Posted by Mr.Jo :

Identity 컬럼이 없던 테이블에 Identity컬럼을 추가 할 경우

임의의(의도치 않은) 순서로 번호가 매겨지게 된다

이를 특정 순서로 정렬하기 위해 여러 테스트를 하던 도중

SELECT * FROM [대상테이블]

매번 할 때와 같은 순서로 번호가 매겨지는걸 발견했다.

따라서 Identity 컬럼을 추가하기 전에 Order by를 하지 않고도 원하는 순서로 정렬되어 출력하도록 하면 되는데

이를 유도하기 위해 해당 테이블에 모든 제약조건이나 인덱스를 삭제하고 원하는 정렬 순서로 Clustered 인덱스를 만들게 되면

(Clustered Index는 테이블내 데이터를 미리 정렬해 둠으로)

Order by없이 정렬된 순서로 출력되기를 유도 할 수 있게 된다(어디까지나 유도이기 때문에 전, 후 확인이 필요하다)

작업 후에 지웠던 제약조건이나 인덱스를 만들고 확인만 하면 끝!


다음은 예제 쿼리

--정렬된 Identity 컬럼 추가
If Object_ID('dbo.Test') Is Not Null
    Drop Table dbo.Test
Go


Create Table dbo.Test
(
     Data1 Int
    ,Data2 Int
    ,Data3 Int
)
Go


Insert Into dbo.Test(Data1, Data2, Data3) Values(43, 123, 42)
Go

Insert Into dbo.Test(Data1, Data2, Data3) Values(23, 5, 52)
Go

Insert Into dbo.Test(Data1, Data2, Data3) Values(154, 12, 11)
Go

Insert Into dbo.Test(Data1, Data2, Data3) Values(23, 23, 23)
Go

Insert Into dbo.Test(Data1, Data2, Data3) Values(42, 12, 53)
Go

Insert Into dbo.Test(Data1, Data2, Data3) Values(533, 21, 521)
Go


--기존에 인덱스가 있다면 인덱스를 삭제하고 원하는 순서로 인덱스 생성하고 작업 완료후 인덱스를 정리
Create Clustered Index IDX_Test_Data1_Data2_Data3 On dbo.Test(Data1 Asc, Data2 Asc, Data3 Asc)
Go


Alter Table dbo.Test Add A Int Identity(1,1)
Go

Select *
From dbo.Test
   
Select *
From
(
    Select *,ROW_NUMBER() Over (Order By Data1 Asc, Data2 Asc, Data3 Asc) As B
    From dbo.Test
) As Test
Where A<>B
Order By A Asc,B Asc
Go


If Object_ID('dbo.Test') Is Not Null
    Drop Table dbo.Test
Go


Posted by Mr.Jo :

작동버젼 : SQL Sserver 2000 이상
사용방법 : [CSV 파일 경로] 수정 후 실행
주의사항 : CSV파일의 첫 줄은 컬럼명이여야 함
설      명 : csv파일을 디비로 불러올 일이 제법 자주 있기에 자동화 시킨 스크립트



USE master;
GO

SET NOCOUNT ON;

DECLARE @FilePath nvarchar(4000);
SET @FilePath = '[CSV 파일 경로]';

IF OBJECT_ID('tempdb.dbo.FirstRow', 'U') IS NOT NULL
	DROP TABLE tempdb.dbo.FirstRow;

CREATE TABLE tempdb.dbo.FirstRow
(
	CSV nvarchar(100)
);

DECLARE @Query nvarchar(4000);

SET @Query =
'
BULK INSERT tempdb.dbo.FirstRow FROM ''' + @FilePath + '''
WITH
(
	  FIRSTROW = 1
	 ,LASTROW = 1
);
';

EXECUTE sp_executesql @Query;


SELECT @Query =
'
IF OBJECT_ID(''tempdb.dbo.CSV'', ''U'') IS NOT NULL
	DROP TABLE tempdb.dbo.CSV;
CREATE TABLE tempdb.dbo.CSV
(
	' + REPLACE(CSV, ',', ' nvarchar(4000),') + ' nvarchar(4000)
)'
FROM tempdb.dbo.FirstRow;

EXECUTE sp_executesql @Query;




SET @Query =
'
BULK INSERT tempdb.dbo.CSV FROM ''' + @FilePath + '''
WITH
(
	   FIRSTROW = 2
	  ,FIELDTERMINATOR = '',''
	  ,ROWTERMINATOR = ''\n''
);
';

EXECUTE sp_executesql @Query;


IF OBJECT_ID('tempdb.dbo.#CSV', 'U') IS NOT NULL
	DROP TABLE #CSV;

SELECT *
INTO #CSV
FROM tempdb.dbo.CSV;

IF OBJECT_ID('tempdb.dbo.FirstRow', 'U') IS NOT NULL
	DROP TABLE tempdb.dbo.FirstRow;
IF OBJECT_ID('tempdb.dbo.CSV', 'U') IS NOT NULL
	DROP TABLE tempdb.dbo.CSV;
GO

이제 CSV파일 내용이 #CSV임시 테이블에 저장되여 다음과 같이 사용 가능
SELECT * FROM #CSV;


Posted by Mr.Jo :

작동버젼 : SQL Sserver 2000, 2005 이상
사용방법 : 실행
주의사항 : Where절을 입맛에 맞게 수정 하여 사용
설      명 : 다른 명령에 의해 대기 상태인 명령어 발견



SQL Server 2000 버젼용

SELECT
     SPID
    ,Status
    ,LogiName AS Login
    ,HostName
    ,blocked AS BlkBy
    ,DB_NAME(dbid) AS DBName
    ,cmd AS Command
    ,cpu AS CPUTime
    ,physical_io AS DiskIO
    ,last_batch AS LastBatch
    ,program_name AS ProgramName
    ,DATEDIFF(MI, last_batch, GETDATE())
FROM master..sysprocesses
WHERE SPID <> @@SPID
  AND DATEDIFF(SS, last_batch, GETDATE()) >= 5
  AND (
		   Blocked <> 0
		OR SPID IN
			(
				SELECT blocked
				FROM master..sysprocesses
				WHERE blocked <> 0
				  AND blocked <> @@SPID
			)
	  )
ORDER BY SPID;
SQL Server 2005 이상 버젼용
SELECT
     a.SPID
    ,a.Status
    ,a.LogiName AS Login
    ,a.HostName
    ,a.Blocked AS BlkBy
    ,DB_NAME(a.dbid) AS DBName
    ,a.Cmd AS Command
    ,a.Cpu AS CPUTime
    ,a.Physical_io AS DiskIO
    ,a.Last_Batch AS LastBatch
    ,a.Program_Name AS ProgramName
    ,b.Text
FROM master.sys.sysprocesses AS a WITH(NOLOCK)
    CROSS APPLY master.sys.dm_exec_sql_text(a.Sql_Handle) AS b
WHERE a.SPID <> @@SPID
  AND
  (
       DATEDIFF(SS, a.Last_Batch, GETDATE()) >= 5
    OR 
	(
		   a.Blocked <> 0
		OR a.SPID IN
			(
				SELECT a.Blocked
				FROM master.sys.sysprocesses
				WHERE a.Blocked <> 0
				  AND a.Blocked <> @@SPID
			)
	)
  )
ORDER BY a.SPID
SQL Server 2005 이상 또 다른 버젼(최신)
SELECT
	 a.Session_ID
	,a.Blocking_Session_ID
	,a.Status
	,c.Login_Name
	,c.Host_Name
	,d.client_net_address
	,d.local_tcp_port
	,c.last_request_start_time
	,DB_NAME(a.Database_ID) AS DBName
	,a.Command
	,a.Reads
	,a.Writes
	,a.CPU_Time
	,a.Logical_Reads
	,c.program_name AS ProgramName
	,b.text
FROM master.sys.dm_exec_requests AS a WITH(NOLOCK)
	CROSS APPLY master.sys.dm_exec_sql_text(a.sql_handle) AS b
	INNER JOIN sys.dm_exec_sessions AS c WITH(NOLOCK) ON a.session_id = c.session_id
	INNER JOIN sys.dm_exec_connections AS d WITH(NOLOCK) ON a.session_id = d.session_id
WHERE a.session_id <> @@SPID
ORDER BY a.session_id
Lock 세션당 걸린 갯수 확인
SELECT request_session_id, COUNT(*) num_locks
FROM sys.dm_tran_locks WITH(NOLOCK)
GROUP BY request_session_id
ORDER BY COUNT(*) desc


Posted by Mr.Jo :