퇴근5분전


이번 프로젝트에서 개량된 도우미 sp시리즈임.
SP 내용은 공개하지 않음!!!( 누구나 만들 수 있는 쿼리이기에... )

 


단축키로 등록해서 사용하면 매우 편리하다.

- SP_JS_OBJECT_EXTENDEDPROPERTY 는 객체의 확장속성등을 정의하는 쿼리와 적용된 내용을 보여준다.


- SP_JS_OBJECT_INFO 는 SP_HELP와 같다 다만 SP를 만들때 사용할 파라미터라든가 설명등을 같이 보여준다.

  기본 정보(객체정보), 컬럼 ( TABLE ), 파라미터( SP, FUNCTION ), RETURN TABLE( FUNCTION ), 객체종속정보

<< FUNCTION 상세보기 >>

<< PROCEDURE 상세보기 >>

<< TABLE 상세보기 >>

- SP_JS_TABLE_SELECT 는 컬럼명을 확장속성으로 병행 표기해준다.


- SP_JS_DEPENDS_HELP 는 제공되는 sp_depends를 수정하여 더 많은 정보들을 보여준다.


- SP_JS_CHANGECOLLATE 은 테이블의 컬럼에 데이타 정렬 속성을 변경할 수 있는 쿼리를 보여준다.

 결과1 : ALTER TABLE ORDERING  ALTER COLUMN CD varchar(20) COLLATE Korean_Wansung_BIN
 결과2 : ALTER TABLE ORDERING  ALTER COLUMN CD varchar(20) COLLATE Korean_Wansung_CI_AS

컬럼이 한두개일땐 모르지만 엄청 많을때 이거 엄청 고된 작업이 된다... 그때 사용하면 된다.

이 SP 들과 연계되는 각종 도우미 프로그램들도 있다...

작업하면서 틈틈히 정리하려고 했던 내용인데
많이는 못하고 일부만 올린다.

#####################################################################################################
## 실행계획 관련해서 찾아본 링크 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
URL : http://rdbms.tistory.com/entry/Order-By-Tuning
DISTINCT : 전체 스캔을 하여 중복된 로우를 제거 한다.
ORDER BY : 전체 스캔을 하여 해당 엑세스가 된 로우를 정렬을 한다.
 
결국 둘다 전체 스캔을 유도 하는 구문입니다.
**  무슨 수를 써던  Order By를 사용하지 않던가 Order By 대상건수를 줄이는 것이 최대 관건이다.
현실적으로 업무상 Order By를 사용하지 않을수는 없을 것이므로  **


/*실행계획 ###############################################################*/
--[Bookmark Lookup] 연산자는 책갈피(행 ID 또는 클러스터링 키)를 사용하여 테이블이나 클러스터형 인덱스에서 해당 행을 조회합니다
--[RID Lookup]은 제공된 RID(행 식별자)를 사용하여 힙을 조회하는 책갈피 조회입니다. 
--   => RID Lookup은 항상 NESTED LOOP JOIN과 함께 사용됩니다. RID Lookup은 물리 연산자입니다.
--      RID Lookup은 Heap Table에서 만 일어난다.(Unique Non-Clustered)
--[Key Lookup] 연산자는 클러스터형 인덱스가 있는 테이블의 책갈피 조회입니다.
--   => Key Lookup은 항상 Nested Loops 연산자와 함께 사용됩니다.
/*[#Tip]
글러스터드 인덱스는 리프레벨에 모든 데이터를 가지고 있기 때문에 같은 컬럼에 넌클러스트를 만드는 경우보다 더 커지게 됩니다 ^^ 룩업이 발생하지 않는다면 같은 컬럼의 클러스터드 보다 넌클러스트 인덱스가 i/o를 좀더 줄일 수도 있습니다  */

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
#####################################################################################################


/*시간 ###############################################################*/
SELECT Current_Timestamp , GETDATE()

SELECT @@DATEFIRST  -- 7 : 일요일임을 뜻함

-- 현재 WEEKDAY 는 요일, WEEK는 주  곧. '2012-07-02' 는 월요일이고, 27번째주가 된다.
SELECT DATEPART( WEEKDAY, '2012-07-02' ), DATEPART( WEEK, '2012-07-02' )


-- DATEPART ? 로 검색되네?
-- http://msdn.microsoft.com/ko-kr/library/ms174420.aspx
SELECT Current_Timestamp
,  Datename(YYYY, Current_Timestamp ) -- YEAR   : YY, YYYY
,  Datename(MM, Current_Timestamp ) -- MONTH  : MM, M
,  Datename(DD, Current_Timestamp ) -- DAY   : DD, D
,  Datename(HH, Current_Timestamp ) -- HOUR   : HH
,  Datename(N, Current_Timestamp )  -- MINUTE  : MI,N
,  Datename(S, Current_Timestamp )  -- SECOND  : SS,S
,  Datename(MS, Current_Timestamp ) -- MILLISECOND : MS
,  DATEPART(YYYY, Current_Timestamp ) AS [DATEPART]  -- DATEPART로 해봄.

-- ISDATE는 CONVERT 함수와 함께 사용하고 CONVERT 스타일 매개 변수가 지정되고
-- 스타일이 0, 100, 9 또는 109가 아닌 경우에만 결정적입니다.
-- http://msdn.microsoft.com/ko-kr/library/ms187347.aspx
select ISDATE( '20120110130200'), ISDATE( '2012-01-10 13:02:00') -- 시간포멧 확인


--지정된 startdate와 enddate 간에 겹쳐지는 지정된 datepart 범위의 수(부호 있는 정수)를 반환합니다.
--http://msdn.microsoft.com/ko-kr/library/ms189794.aspx
--두 시각의 START - END = RESULT
--DATEPART( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND )값에 따라 체크(분단위까지 유효!)됨.
SELECT DATEDIFF( DAY , '2012-01-11 13:01:00', Current_Timestamp )
/*시간 ###############################################################*/

 

/* 구성함수 ##########################################################*/ 

-- 요청이 들어 오는 고유한 연결의 연결 속성에 대한 정보를 반환합니다
-- http://msdn.microsoft.com/ko-kr/library/bb895240.aspx
select ConnectionProperty('local_net_address') , ConnectionProperty('local_tcp_port')

--현재 사용 중인 언어의 이름을 반환합니다.
select @@Language

--현재 서버에 설정되어 있는 decimal과 numeric 데이터 형식의 전체 자릿수 수준을 반환합니다.
select @@Max_Precision

-- 저장 프로시저가 다른 저장 프로시저를 호출하거나 CLR(공용 언어 런타임) 루틴, 유형
-- 또는 집계를 참조하여 관리 코드를 실행할 때마다 중첩 수준이 증가합니다.
-- 최대값 32를 초과하면 트랜잭션이 종료됩니다.
select @@Nestlevel

-- 서버명
select @@Servername

-- 서버sql버젼
select @@Version

-- 서비스 명
select @@Servicename

-- text 사이즈
select @@Textsize
/* 구성함수  ##########################################################*/ 

 
/*메타데이터 함수  ###################################################*/
Col_Length()
Col_Name()
Columnproperty()
Db_Id()
Db_Name()
Index_Col()
Indexkey_Property()
Indexproperty()
Typeproperty()
Object_Id()
Object_Name()
Objectproperty()
Objectpropertyex()
Sql_Variant_Property()
/*메타데이터 함수  ###################################################*/


 

'# 7) 데이타베이스 > Ms-Sql' 카테고리의 다른 글

MS-SQL] 테이블 스키마 생성 추출 쿼리.  (0) 2012.11.21
MS-SQL] SP_JS_시리즈...  (0) 2012.03.02
MS-SQL ] 1:N 관계에서 n순번 따기...  (0) 2012.03.02
[MS-SQL] 음... 잡다?  (0) 2012.01.02
MS-SQL ] default  (0) 2011.11.18

 이번 프로젝트에서 업체와 관련된 테이블 쿼리에서 업체에 등록된 면허들에 대한 정보를 피벗해서 한번에 보여줘야 하는
쿼리를 처리하면서 잔머리 써본 쿼리 중 짧은 예로 작성해본다.


/*KEY [ tb_1 ( 1 : N ) tb_n ]#################################################################*/
SELECT *
FROM (
 values
  ('a', 'Nm:a')
 , ('b', 'Nm:b')
 , ('c', 'Nm:c')
 , ('d', 'Nm:d')
 , ('e', 'Nm:e')
) as tb_1( K, N )
 
SELECT *
FROM (
 values
  ('a', 'm1:a1')
 , ('a', 'm2:a2')
 , ('b', 'm1:b1')
 , ('e', 'm1:e1')
 , ('e', 'm2:e2')
) as tb_n( K, N )
/*순번 따기 ##################################################################################*/


SELECT
 tb_1.K
, tb_1.N
, ROW_NUMBER() OVER ( ORDER BY tb_1.K ) - RANK() OVER ( ORDER BY tb_1.K ) + 1 [SN_SEQ]
,  tb_n.N
FROM (
 values
  ('a', 'Nm:a')
 , ('b', 'Nm:b')
 , ('c', 'Nm:c')
 , ('d', 'Nm:d')
 , ('e', 'Nm:e')
) as tb_1( K, N )
LEFT OUTER JOIN
(
 values
  ('a', 'm1:a1')
 , ('a', 'm2:a2')
 , ('b', 'm1:b1')
 , ('e', 'm1:e1')
 , ('e', 'm2:e2')
) as tb_n( K, N )
ON tb_1.K = tb_n.K

결과 --- 


보면 a에 대해 1, 2 순번을 따 놓은게 보인다.

이를 이용해 그룹바이를 통해 CASE로 골라내면 옆으로 늘어뜨리는게 가능하다.

다만 CASE로 처리할수 있는 부분이 코드에 따라 달라지므로 이걸 동적으로 처리할 수 있다면 좋겠지만...

우선은 제한적으로 5개, 10개 등으로 제한된 갯수를 표현하는데 무리없는 쿼리라고 보면 된다.

'# 7) 데이타베이스 > Ms-Sql' 카테고리의 다른 글

MS-SQL] SP_JS_시리즈...  (0) 2012.03.02
MS-SQL ] MSDN 일부 정리!  (0) 2012.03.02
[MS-SQL] 음... 잡다?  (0) 2012.01.02
MS-SQL ] default  (0) 2011.11.18
MS-SQL ] 오류 메세지 정리  (0) 2011.11.17


SQL을 다룰때마다 느끼는거지만... 참 재미있는게 많은데..

모르면 손가락 아프게 열심히 쳐야 한다는 사실...

항상 사용하는 것들 또 MSDN을 찾기 구찮아서 정리 해둔다..

아래 내용이면 테이블에 속성이나 자료형 길이등을 뽑아내서 스크립트화 가능한다... 

index_col( object_name( t.object_id ), i.index_id, c.column_id )  인덱스 컬럼인지 확인해준다.

type_name( c.system_type_id )  타입명을 반환

case 
when lower(type_name( c.system_type_id )) in ('char', 'varchar', 'nchar' ,'nvarchar', 'text' )  
then '('+convert( varchar(10), columnproperty( c.object_id, c.name, 'precision' ) )+')'       
when lower(type_name( c.system_type_id )) in ('numeric','decimal' ) 
then '('+ convert(varchar, c.precision) + ',' + convert(varchar, c.scale)+')'    
when lower(type_name( c.system_type_id )) in ('float','datetime', 'smalldatetime', 'tinyint', 'int', 'bigint' ) 
then ''           
else ''           
end  

요건 타입에 사용한 길이를 가져오는것인데...
원래 columnproperty( c.object_id, c.name, 'precision' )  이것인데...
잘 안된다.  총 길이를 자꾸 뱉어내서 정수형 INT, BIGINT같은건 길이가 나타남

 sys.tables  테이블들...

 sys.columns  컬럼들...

 sys.index_columns 인덱스컬럼들...

 sys.extended_properties  확장속성들...

 sys.foreign_key_columns  참조키 컬럼들...


DECLARE @TABLE_NAME NVARCHAR(776) = '테이블명'
 
select  [tablename]  = object_name( c.object_id ),
  [columnname] = c.name,
  [columndesc] = isnull(e.value, ''),
  [pk/fk]   = ltrim( rtrim( case
        when isnull( index_col( object_name( t.object_id ), i.index_id, c.column_id ),'') <> ''
        then 'pk'
        else ''
        end + '' +     
        case
        when isnull( f.constraint_column_id , '' ) <> ''
        then 'fk'
        else ''
        end )),
     [allowIsNull]  = isnull(  case when c.is_nullable = 0 then 'no' end , ''),
  [typename]  = type_name( c.system_type_id ),
  [columnlength] = case
        when lower(type_name( c.system_type_id )) in ('char', 'varchar', 'nchar' ,'nvarchar', 'text' ) 
        then '('+convert( varchar(10), columnproperty( c.object_id, c.name, 'precision' ) )+')'      
        when lower(type_name( c.system_type_id )) in ('numeric','decimal' )
        then '('+ convert(varchar, c.precision) + ',' + convert(varchar, c.scale)+')'   
        when lower(type_name( c.system_type_id )) in ('float','datetime', 'smalldatetime', 'tinyint', 'int', 'bigint' )
        then ''          
        else ''          
        end
from sys.tables t
inner join sys.columns c
on t.object_id = c.object_id -- and t.schema_id = 7
left outer join sys.index_columns i    
on c.object_id = i.object_id and c.column_id = i.column_id 
left outer join sys.extended_properties e         
 on c.object_id = e.major_id and c.column_id = e.minor_id and e.class = 1       
left outer join  sys.foreign_key_columns f     
on c.object_id = f.parent_object_id and c.column_id = f.parent_column_id 
WHERE @TABLE_NAME = case nullif( @TABLE_NAME, '') when '' then '' else OBJECT_NAME( t.object_id ) end  
order by t.name, c.is_nullable, c.name



이 구문이면 테이블정보를 쉽게 파악이 가능하고

확장속성에 스크립트를 걸어두면 속성이 컬럼명 옆에 붙어 나오므로 보기 더 좋음.

이걸 편집하면 테이블 스키마는 쉽게 뽑아낼 수 있음.

참고 # SP_DEPENDS 를 편집에서 나만의 프로시져로 만들어 사용하기도 한다..
각종 시스템 프로시져를 편집에서 사용이 편리한 놈으로 개조해서 사용하기도 함!!!



'# 7) 데이타베이스 > Ms-Sql' 카테고리의 다른 글

MS-SQL ] MSDN 일부 정리!  (0) 2012.03.02
MS-SQL ] 1:N 관계에서 n순번 따기...  (0) 2012.03.02
MS-SQL ] default  (0) 2011.11.18
MS-SQL ] 오류 메세지 정리  (0) 2011.11.17
MS-SQL 2008] Values 의 새로운 발견!!?  (1) 2011.11.11


음 기본값 사용에 있어서... 전에 msdn을 찾아 본 적 있는데...
 
DateTime 도 적용이 되는지?? 확인해보았다.

declare @tb table
(
       dt varchar(20) default Convert(varchar(20), Getdate() , 121 )
)

Insert into @tb values( default );

select * from @tb;


잘 된다!!

/*
declare @i int = 1111111111111111111111111111
메시지 8115, 수준 16, 상태 2, 줄 2
expression을(를) 데이터 형식 int(으)로 변환하는 중 산술 오버플로 오류가 발생했습니다.
*/
 

/*
select CONVERT( varchar(10),
'aaaaaaaaaaaaaaaa' )
'aaaaaaaaaa' -- 결과
*/


/*
 declare @v table
 (
  valuedata varchar(4)
 )

 insert into @v values (  '2132132132132132321' )
 메시지 8152, 수준 16, 상태 14, 줄 8
 문자열이나 이진 데이터는 잘립니다.

*/

/*
 declare @v INT = '본사'  -- 메시지 245, 수준 16, 상태 1, 줄 3
 varchar 값 '본사'을(를) 데이터 형식 int(으)로 변환하지 못했습니다.
*/




SELECT a, b, c FROM (
VALUES
('C', 1, 'H' ) ,
('C', 2, 'I' ),
('C', 3, 'H' ),
('B', 2, 'H' ),
('B', 3, 'H' ),
('B', 2, 'I' ),
('C', 3, 'H' ),
('A', 3, 'I' )) AS Tb(a, b,c);


우아... 쥑인답!!!

쿼리 테스트 할때 구지... 어렵게 할필요가 없네???

또는 Union All 걸어가면서 만들었던것도... 이제 바이 바이.. ~

 EX )

SELECT NM, SUM( SM ) SM, ISNULL( MAX(H)+'/', '' ) + ISNULL( MAX(I) , '' ) HI
FROM
(
 SELECT NM, SUM( SMALL ) SM , case KIND when 'H' then 'H' end  H, case KIND when 'I' then 'I' end  I
 FROM
 (
  SELECT NM, SMALL, KIND
  FROM (VALUES
  ('C', 1, 'H' ) ,
  ('C', 2, 'I' ),
  ('C', 3, 'H' ),
  ('B', 2, 'H' ),
  ('B', 3, 'H' ),
  ('B', 2, 'I' ),
  ('C', 3, 'H' ),
  ('A', 3, 'I' )) AS Tb( NM, SMALL, KIND )
 ) O
 GROUP BY NM, KIND
) M
GROUP BY NM


이것도 키 등록 후 테이블 내용을 볼때 컬럼명이 아닌 이름으로 볼수있다...

단점, WHERE 문... ㅡ.,ㅡ;;


/*     
   
 윤지송    
    
 테이블의 데이타를 1000개를 쿼리 하되      
      
 컬럼명을 HEADER 가 등록된 테이블은 해당 테이블의 헤더를 컬럼명으로 사용함.      
     
*/     
CREATE PROC dbo.sp_table_select     
 @TABLE_NM NVARCHAR(776)  = ''    
as     
     
IF( RTRIM(@TABLE_NM) = '' OR @TABLE_NM IS NULL )     
BEGIN     
 PRINT(' ^ ______ ^')   
 RETURN;   
END     
     
      
DECLARE @QUERY NVARCHAR(MAX)     
SET @QUERY = ''     
      
 ;WITH TABLE_COLS ( COLUMN_ID, NAME  )     
 AS     
 (     
 SELECT COLUMN_ID, NAME     
 FROM SYS.COLUMNS     
 WHERE OBJECT_ID = OBJECT_ID( @TABLE_NM )     
 ),     
 COLS_ATTS ( NAME , HEADER )     
 AS     
 (     
 SELECT objname AS NAME , value AS HEADER         
 FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', @TABLE_NM, 'column', default)     
 )      
 SELECT-- C.COLUMN_ID,C.NAME, ISNULL(A.HEADER, '') HEADER,     
  @QUERY = @QUERY + C.NAME +  ISNULL( ' AS [' + CONVERT(VARCHAR(100),  A.HEADER ) + ']' ,' AS '+ C.NAME ) + ', '      
 FROM TABLE_COLS C LEFT OUTER JOIN COLS_ATTS A     
 ON C.NAME = A.NAME  COLLATE  Korean_Wansung_CI_AS     
      
--SELECT @QUERY      
EXEC( 'SELECT TOP 100 '+ @QUERY + ' '''' AS [END__]' + 'FROM '+ @TABLE_NM )


 
DECLARE @TABLE_NAME NVARCHAR(776)
SET @TABLE_NAME = PARSENAME( '테이블 명' , 1 )

select COUNT( column_id ) from sys.columns
where OBJECT_ID = OBJECT_ID(@TABLE_NAME)

SELECT
a.name, b.value,
case when b.name is null then '' else
'EXEC sys.sp_dropextendedproperty '+
'@name=N''MS_Description'', '+
'@level0type=N''SCHEMA'', @level0name=N''dbo'', '+
'@level1type=N''TABLE'', @level1name=N'''+OBJECT_NAME(a.OBJECT_ID)+''', '+
'@level2type=N''COLUMN'', @level2name=N'''+a.NAME+'''' end as DropEx,

'EXEC sys.sp_addextendedproperty '+
'@name=N''MS_Description'', @value=N'''+'{0}'+''', '+
'@level0type=N''SCHEMA'', @level0name=N''dbo'', '+
'@level1type=N''TABLE'', @level1name=N'''+OBJECT_NAME(a.OBJECT_ID)+''', '+
'@level2type=N''COLUMN'',@level2name=N'''+a.NAME+'''' as AddEx
FROM sys.columns a
left outer join
(
 SELECT OBJECT_ID( @TABLE_NAME ) object_id , objtype, objname , name, value
 FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', @TABLE_NAME, 'column', default)
-- order by object_id, objname COLLATE  Korean_Wansung_CI_AS asc
) b
on a.object_id = b.object_id and a.name COLLATE  Korean_Wansung_CI_AS = b.objname COLLATE  Korean_Wansung_CI_AS
WHERE a.OBJECT_ID = OBJECT_ID(@TABLE_NAME)


-- 테이블 설명 추가...

EXEC sys.sp_addextendedproperty
@name = N'MS_Description',
@value = N'테이블 추가 설명 ex',
@level0type = N'SCHEMA', @level0name = dbo,
@level1type = N'TABLE',  @level1name =  '테이블 명' ;

SELECT OBJECT_ID(  '테이블 명' ) object_id , objtype, objname , name, value
FROM fn_listextendedproperty(NULL, 'schema', 'dbo', 'table',  '테이블 명', default, default)
where name = 'MS_Description'

 


전에 만들어둔게 있었는데....

문제가 조금 있으니 쿼리를 수정함...

이 프로시져는 등록한 데이타 베이스에서만 사용이 가능하다.

전체 DB에서 사용할 수 있는 방법을 찾아봐야겠다.

-- TAG 검색 되게 PRMS, prms

수정 PK , FK ... 정보 출력.

/*   
작성자 : 윤지송    
   
테이블 컬럼의 속성 보는 쿼리!!   
   
   
SqlManagement Studio에 도구 -> 옵션 -> 일반탭 : 키보드    
   
매크로 지정하는 화면에서    
   
키에 exec SP_TABLE_COLUMN_INFO 를 입력해두고...   
   
쿼리실행창에서 보고싶은 테이블이름 셀렉팅 하고 매크로 키를 누르면 프로시져가 실행되어진다.    
   
단, 키등록후 매니져를 껐다 켜야 되드랑!!    
   
*/   
ALTER PROC DBO.SP_TABLE_COLUMN_INFO   
(   
 @TABLENAME nvarchar(776) = NULL   
)   
AS
 
 
 select distinct
  c.object_id , c.name,
   ltrim( rtrim( case when isnull( index_col( @TABLENAME , i.index_id, C.column_id ),'') <> '' then 'PK' else '' end + ' '+
  case when isnull( f.constraint_column_id , '' ) <> '' then 'FK' else '' end )) as [KEY] ,
  isnull(e.value,'') ExName , isnull( t.name ,'') TypeName,   
  c.COLUMN_ID,                
  CONVERT( VARCHAR,  c.NAME ) AS[NAME],               
  UPPER(t.NAME) AS [DTYPE] ,               
  CASE WHEN UPPER(t.NAME) IN ('CHAR','VARCHAR','NVARCHAR','NCHAR','TEXT' )  THEN CASE c.MAX_LENGTH WHEN -1 THEN '(MAX)'    
          ELSE '('+ CONVERT( VARCHAR, c.MAX_LENGTH / ( CASE WHEN LEFT(t.NAME,1) = 'N' THEN 2 ELSE 1 END ) ) +')'     
        END    
   WHEN UPPER(t.NAME) IN ('NUMERIC','DECIMAL' ) THEN '('+ CONVERT(VARCHAR, c.PRECISION) + ',' + CONVERT(VARCHAR, c.SCALE)+')'   
   ELSE ''    
  END AS [LEN],               
  '-- ' + isnull( CONVERT( VARCHAR,  e.VALUE  ) , c.Name ) AS [DESC],               
                
  '@'+CONVERT( VARCHAR,  c.NAME )+' ' + UPPER(t.NAME) +  CASE WHEN UPPER(t.NAME) IN ('CHAR','VARCHAR','NVARCHAR','NCHAR') THEN CASE c.MAX_LENGTH WHEN -1 THEN '(MAX)'    
            ELSE '('+ CONVERT( VARCHAR, c.MAX_LENGTH / ( CASE WHEN LEFT(t.NAME,1) = 'N' THEN 2 ELSE 1 END ) ) +')'    
          END    
           WHEN UPPER(t.NAME) IN ('NUMERIC','DECIMAL' ) THEN '('+ CONVERT(VARCHAR, c.PRECISION) + ',' + CONVERT(VARCHAR, c.SCALE)+')'   
           ELSE ''    
      END +    
   ', -- ' + isnull( CONVERT( VARCHAR,  e.VALUE  ) , '') AS  PROC_PRMS,   
             
  '@'+CONVERT( VARCHAR,  c.NAME + ',' ) AS [PRMS] ,          
          
  'AND'  AS [AND],         
  CONVERT( VARCHAR,  c.NAME + ' = ' ) + '@'+CONVERT( VARCHAR,  c.NAME  ) AS [WPRMS]       
  ,   
  '' as ['        공백         ']   
  ,c.*       
 from sys.columns c left outer join sys.extended_properties e   
 on c.Object_id = e.MAJOR_ID and c.Column_Id = e.Minor_id and e.CLASS = 1   
 left outer join SYS.TYPES t     
 on c.SYSTEM_TYPE_ID = t.SYSTEM_TYPE_ID AND t.NAME <> 'SYSNAME'   
 left outer join sys.index_columns i
 on c.object_id = i.object_id and c.column_id = i.column_id
 left outer join  sys.foreign_key_columns f
 on c.object_id = f.parent_object_id and c.column_id = f.parent_column_id
 where c.Object_id = OBJECT_ID( @TABLENAME )   
 ORDER BY C.column_id
   
SELECT OBJECT_ID(OBJNAME) OBJECT_ID , objtype, objname , name, value 
FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', @TABLENAME, default, default)