2014-09-26 3 views
1

열 정의를 필드의 최대 길이로 변경하는 코드를 동적으로 만들려고합니다.동적 T-SQL - 필드의 최대 길이로 열 정의 변경

데이터베이스의 내용은 변경되지 않습니다.

여기까지 제가 가지고있는 것이지만, 최대 길이 쿼리를 별도로 실행하여 숫자를 얻을 수는 없습니다. 내가 어디로 잘못 가고 있니?

감사합니다.

DECLARE @SQL_STMT VARCHAR(MAX) = 'DECLARE @query nvarchar(max);' 

SELECT @SQL_STMT = @SQL_STMT 
    + 'SET @query =''ALTER TABLE ' 
    + TABLE_NAME 
    + ' ALTER COLUMN ' 
    + COLUMN_NAME 
    + ' ' 
    + DATA_TYPE 
    + '('' +CAST((SELECT MAX(DATALENGTH(' 
    + COLUMN_NAME 
    + ')) FROM ' 
    + TABLE_NAME 
    + ') as nvarchar(max))+'') '' 
    exec(@query);' 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE = 'nvarchar' 

PRINT(@SQL_STMT) 
+0

당신은 얼마나 많은 길이 개까지 VARCHAR의 열을 변경하려면 ??? 이것은 정확히 당신이 뭘하고 싶어하는지 명확하지 않습니다 ?? –

+0

단일 필드의 최대 길이까지. 예를 들어, emp에서 max (len (empname))를 선택하십시오 –

+2

왜 세계에서이 작업을 수행합니까? 이로 인해이 데이터베이스를 사용하는 응용 프로그램이 손상 될 수 있습니다. 프런트 엔드에 유효성 검사가 있기 때문에 데이터 오류가 잘릴 수 있습니다. 당신은 단지 varchar 컬럼을 변경하기 때문에 당신은 아무것도 얻지 못할 것입니다. 후행 공백을 고려하지 않은 LEN을 사용하기 때문에 오류가 발생할 수 있음은 물론입니다. –

답변

0

편집 내 첫 번째 버전은 정제되지 않은만큼, 여기에 내가 테스트 한 새로운 버전이다 의 열을 ALTER TABLE 문에 입력하십시오. 일반적으로 동일한 성명에서 DDL (데이터 설명 언어, 예 : CREATE, ALTER, DROP)과 DML (데이터 조작 언어, 예 : SELECT, INSERT, UPDATE)을 함께 사용할 수 없습니다.

이것은 작업을 수행하기 위해 동적 SQL을 사용해야한다는 것을 의미합니다. 동적 SQL을 사용하여 저장하고 재사용 할 수있는 정적 SQL을 빌드 할 수 없습니다. 필드의 최대 길이를 검색하여 변수에 저장 한 다음 ALTER 문을 구성하고 마지막으로 EXEC()ALTER 문을 구성해야합니다. 가장 쉬운 방법은 INFORMATION_SCHEMA.COLUMNS을 통한 커서를 사용하는 것이지만 이중 동적 SQL도 사용할 수 있습니다. 즉, 동적 SQL 자체가 동적 SQL을 생성하는 동적 SQL입니다. 그러나 디버깅이 훨씬 더 어렵습니다.

그 외에도 내가하는 일의 타당성에 의문을 제기합니다. 간단히 말해서이 코드를 사용할 필요가 없습니다. 데이터베이스 스키마를 변경하면 성능에 상당한 영향을 미치기 때문에 데이터베이스 스키마는 비교적 고정적이어야합니다. 열의 크기를 변경하면 데이터베이스에 물리적으로 디스크에 데이터를 저장하는 방식을 변경해야한다는 것을 데이터베이스 엔진에 알리면 가볍게 또는 정기적으로 수행해야하는 작업이 아닌 것입니다. 사용자 요구를 수용 할만큼 충분히 큰 값을 설정하면 훨씬 더 나아질 것입니다. 현대의 RDBMS는 비효율적으로 데이터를 저장하지 않는 것이 훨씬 낫지 만 열 크기를 변경하는 것은 여전히 ​​가난한 실천입니다.

+0

이 코드를 사용해 보셨습니까 ??? 컴파일하는거야? –

+0

제 첫 번째 버전이 작동하지 않았습니다 (시도 할 샌드 박스 데이터베이스가 없었습니다).하지만 기능적 해결책으로 제 대답을 편집했습니다. – Ndech

+0

환호 친구[email protected]는 –

-1

당신은 크기로 SELECT 문 또는 정수 변수를 사용할 수 없습니다

DECLARE @SQL_STMT VARCHAR(MAX) = '' 

SELECT @SQL_STMT = @SQL_STMT 
    + '''ALTER TABLE ' 
    + TABLE_NAME 
    + ' ALTER COLUMN ' 
    + COLUMN_NAME 
    + ' ' 
    + DATA_TYPE 
    + '('' SELECT MAX(LEN(' 
    + COLUMN_NAME 
    + ')) FROM ' 
    + TABLE_NAME 
    + ''') '' 
    ' 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE DATA_TYPE = 'varchar' 

PRINT(@SQL_STMT) 
0

I 생각이 아니 친구 해요,하지만 당신이 원하는 것을 수행해야합니다

DECLARE @SQL_STMT VARCHAR(MAX) = '' 

SELECT 
    IDENTITY(int,1,1) as ID, -- for later update 
    'ALTER TABLE ' 
    + c.TABLE_NAME 
    + ' ALTER COLUMN ' 
    + c.COLUMN_NAME 
    + ' ' 
    + c.DATA_TYPE 
    + '(' P1 

    , ' MAX(LEN(' 
    + c.COLUMN_NAME 
    + ')' 
    +') FROM ' 
    + c.TABLE_NAME P2 

    , ') ' P3 
into #tmp  
FROM INFORMATION_SCHEMA.Tables t 
JOIN INFORMATION_SCHEMA.Columns c 
on c.TABLE_CATALOG= t.TABLE_CATALOG 
    and c.TABLE_SCHEMA=t.TABLE_SCHEMA 
    and c.TABLE_NAME=t.TABLE_NAME 
where TABLE_TYPE='BASE TABLE' -- only Tables not views 
and DATA_TYPE = 'varchar' 

Select @SQL_STMT='' -- collect ID + Max info e.g. SELECT 1, MAX(LEN(FirstName)) FROM user_info 
Select @[email protected]_STMT + 'SELECT '+ CAST(ID as varchar(10)) + ', '+ P2 +CHAR(13) 
from #tmp 

Declare @a table (ID Integer,Size Integer) -- table for ID and Len 
--print @SQL_STMT 

insert into @a Exec (@SQL_STMT) -- fill table by executing block 

        -- define a minimum size if 0 
Update #tmp set P2 = Case When Size<1 then 1 else Size end -- update p2 
From @a a where a.ID = #tmp.ID 

Select @SQL_STMT='' 
Select @[email protected]_STMT + P1 + P2 + P3 +CHAR(13) 
from #Tmp 

print @SQL_STMT 

Exec(@SQL_STMT) 


Drop table #tmp