Solved

Converting nvarchar columns datatype to varchar datatype thru scripting

Posted on 2004-03-30
11
1,877 Views
Last Modified: 2008-02-01
Hello.

I was given a client SQL database that had be converted from Access to SQL 2000.  My problems is that the data was pull in as NVarchar instead of Varchar.  In another example here in EE http://www.experts-exchange.com/Databases/Microsoft_SQL_Server/Q_20869435.html?query=converting+nvarchar+to+varchar&searchType=topic the script seem to work if I follow the converstation however I am expected to set the width to 500 char.  I was wondering if there was a way for the script to automaticly set the width.  Here is an example of the orginal converting script


DECLARE curFixColsGetTables CURSOR
FOR SELECT TABLE_NAME
FROM information_schema.tables
WHERE table_Type = 'Base Table'
AND table_name <> 'dtproperties'

OPEN curFixColsGetTables
FETCH NEXT FROM curFixColsGetTables into @TableName

WHILE @@FETCH_STATUS = 0
BEGIN
 
  DECLARE curFixColsGetCols CURSOR
  FOR SELECT COLUMN_NAME
  FROM information_schema.columns
  WHERE table_name = @TableName AND DATA_TYPE = 'nvarchar'

  OPEN curFixColsGetCols
  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName
 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    SELECT @strSQL = 'ALTER TABLE ' + @TableName
           + ' ALTER COLUMN ' + @ColumnName
           + ' varchar(500)'
    PRINT @strSQL
    EXEC  SP_EXECUTESQL @strSQL

    FETCH NEXT FROM curFixColsGetCols
    INTO @ColumnName
  END
  CLOSE curFixColsGetCols
  DEALLOCATE curFixColsGetCols
 
  FETCH NEXT FROM curFixColsGetTables
  INTO @TableName
  END
CLOSE curFixColsGetTables
DEALLOCATE curFixColsGetTables

So if the NVarchar width is NVarchar(60) then I think that I would like for this to be Varchar(60)

Thanks

James
0
Comment
Question by:thumper631
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
11 Comments
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 10714884
Try this:

DECLARE @ColumnLength SMALLINT

DECLARE curFixColsGetTables CURSOR
FOR SELECT TABLE_NAME, CHARACTER_MAXIMUM_LENGTH
FROM information_schema.tables
WHERE table_Type = 'Base Table'
AND table_name <> 'dtproperties'

OPEN curFixColsGetTables
FETCH NEXT FROM curFixColsGetTables into @TableName, @ColumnLength

WHILE @@FETCH_STATUS = 0
BEGIN
 
  DECLARE curFixColsGetCols CURSOR
  FOR SELECT COLUMN_NAME
  FROM information_schema.columns
  WHERE table_name = @TableName AND DATA_TYPE = 'nvarchar'

  OPEN curFixColsGetCols
  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName
 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    SELECT @strSQL = 'ALTER TABLE ' + @TableName
           + ' ALTER COLUMN ' + @ColumnName
           + ' varchar(' + CAST(@ColumnLength AS VARCHAR(5)) + ')'
    PRINT @strSQL
    --EXEC  SP_EXECUTESQL @strSQL

    FETCH NEXT FROM curFixColsGetCols
    INTO @ColumnName, @ColumnLength
  END
  CLOSE curFixColsGetCols
  DEALLOCATE curFixColsGetCols
 
  FETCH NEXT FROM curFixColsGetTables
  INTO @TableName
  END
CLOSE curFixColsGetTables
DEALLOCATE curFixColsGetTables
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 10714898
CORRECTION:

The first FETCH should be:

FETCH NEXT FROM curFixColsGetCols INTO @ColumnName, @ColumnLength

[rather than:  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName]

0
 

Author Comment

by:thumper631
ID: 10715647
Scott.

I received the following 3 errors when running the script

Server: Msg 137, Level 15, State 1, Line 10
Must declare the variable '@TableName'.

Server: Msg 137, Level 15, State 1, Line 22
Must declare the variable '@ColumnName'.

Server: Msg 137, Level 15, State 1, Line 29
Must declare the variable '@strSQL'.

Thx

James
0
Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 10715786
I don't what the declarations should most accurately be, since those variables were in your original code, I didn't add them.  They should use whatever declarations they were using before.

I did one new variable, so I added a DECLARE for it.
0
 
LVL 50

Expert Comment

by:Lowfatspread
ID: 10715949
you don't really need all the cursors etc...

just run this...

SELECT 'ALTER TABLE [' + TABLE_NAME + '] ALTER COLUMN [' + column_name + '] varchar('
 + convert(char(10),CHARACTER_MAXIMUM_LENGTH )
FROM information_schema.tables as t
inner Join
 (select * from information_schema.columns
    Where DATA_TYPE = 'NVARCHAR') as c
 on t.table_name=c.table_name
and t.table_schema=c.table_schema
and t.table_catalog=c.table_catalog
WHERE t.table_Type = 'Base Table'
AND t.table_name <> 'dtproperties'
order by 1

and then execute the output.
0
 

Author Comment

by:thumper631
ID: 10716089
Ok, my orginial sql script copy was incomplete.  The code with the addition that Scott made is now the following.......

set nocount on
declare @ColumnName varchar(255)
declare @TableName  varchar(255)
declare @strSQL nvarchar(255)
DECLARE @ColumnLength SMALLINT

DECLARE curFixColsGetTables CURSOR
FOR SELECT TABLE_NAME, CHARACTER_MAXIMUM_LENGTH
FROM information_schema.tables
WHERE table_Type = 'Base Table'
AND table_name <> 'dtproperties'

OPEN curFixColsGetTables
FETCH NEXT FROM curFixColsGetTables into @TableName, @ColumnLength

WHILE @@FETCH_STATUS = 0
BEGIN
 
  DECLARE curFixColsGetCols CURSOR
  FOR SELECT COLUMN_NAME
  FROM information_schema.columns
  WHERE table_name = @TableName AND DATA_TYPE = 'nvarchar'

  OPEN curFixColsGetCols
  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName, @ColumnLength
 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    SELECT @strSQL = 'ALTER TABLE ' + @TableName
           + ' ALTER COLUMN ' + @ColumnName
           + ' varchar(' + CAST(@ColumnLength AS VARCHAR(5)) + ')'
    PRINT @strSQL
    --EXEC  SP_EXECUTESQL @strSQL

    FETCH NEXT FROM curFixColsGetCols
    INTO @ColumnName, @ColumnLength
  END
  CLOSE curFixColsGetCols
  DEALLOCATE curFixColsGetCols
 
  FETCH NEXT FROM curFixColsGetTables
  INTO @TableName
  END
CLOSE curFixColsGetTables
DEALLOCATE curFixColsGetTables

The error that I now receiving is

Server: Msg 207, Level 16, State 3, Line 9
Invalid column name 'CHARACTER_MAXIMUM_LENGTH'.

The problem with the suggest that Lowfatspread has suggest is that I have to do this for 30+ tables.

Please keep the suggestion coming as I am learning more and more on SQL each day.....

James


0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 10716685
D'OH, SORRY, I added the column to the wrong query.  Below is corrected code (minus the variable DECLAREs):


DECLARE curFixColsGetTables CURSOR
FOR SELECT TABLE_NAME
FROM information_schema.tables
WHERE table_Type = 'Base Table'
AND table_name <> 'dtproperties'

OPEN curFixColsGetTables
FETCH NEXT FROM curFixColsGetTables into @TableName

WHILE @@FETCH_STATUS = 0
BEGIN
 
  DECLARE curFixColsGetCols CURSOR
  FOR SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH
  FROM information_schema.columns
  WHERE table_name = @TableName AND DATA_TYPE = 'nvarchar'

  OPEN curFixColsGetCols
  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName, @ColumnLength
 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    SELECT @strSQL = 'ALTER TABLE ' + @TableName
           + ' ALTER COLUMN ' + @ColumnName
           + ' varchar(' + CAST(@ColumnLength AS VARCHAR(5)) + ')'
    PRINT @strSQL
    --EXEC  SP_EXECUTESQL @strSQL

    FETCH NEXT FROM curFixColsGetCols
    INTO @ColumnName, @ColumnLength
  END
  CLOSE curFixColsGetCols
  DEALLOCATE curFixColsGetCols
 
  FETCH NEXT FROM curFixColsGetTables
  INTO @TableName
  END
CLOSE curFixColsGetTables
DEALLOCATE curFixColsGetTables
0
 
LVL 69

Assisted Solution

by:Scott Pletcher
Scott Pletcher earned 400 total points
ID: 10716718
CORRECTION:

Change the EXEC to what's below (including ucommenting it :-) (I did that for my own test) :

EXEC (@strSQL)

you don't need sp_executeSQL here and it may cause conversion issues.
0
 
LVL 50

Accepted Solution

by:
Lowfatspread earned 100 total points
ID: 10716808
sorry why is 30+ tables a problem...

you only get the same ouput as you'd generate from the cursor example.......

if you want to process it automatically then

declare @N int
SELECT 'ALTER TABLE [' + TABLE_NAME + '] ALTER COLUMN [' + column_name + '] varchar('
 + convert(char(10),CHARACTER_MAXIMUM_LENGTH )  as SQL, Identity(int,1,1) as rowno into #temp
FROM information_schema.tables as t
inner Join
 (select * from information_schema.columns
    Where DATA_TYPE = 'NVARCHAR') as c
 on t.table_name=c.table_name
and t.table_schema=c.table_schema
and t.table_catalog=c.table_catalog
WHERE t.table_Type = 'Base Table'
AND t.table_name <> 'dtproperties'
order by 1
Set @n = @@ROWCOUNT

Declare @I int
Declare @SQLSTR Varchar(8000)
set @i=1

While @i <=@N
begin
     Select @sqlstr=SQL,@i=@i+1 from #temp where @rowno=@i
--  PRINT @SQLSTR  
     EXEC (@SQLSTR)
End


     
0
 

Author Comment

by:thumper631
ID: 10717396
Here is the finally solution that I used for anyone else who may need to use this

--  Changes all NVarChar --> VarChar in your database
--  thx to Scott Pletcher of Expert Exchange to helping me to complete this

set nocount on
declare @ColumnName varchar(255)
declare @TableName  varchar(255)
declare @strSQL nvarchar(255)
DECLARE @ColumnLength SMALLINT

DECLARE curFixColsGetTables CURSOR
FOR SELECT TABLE_NAME
FROM information_schema.tables
WHERE table_Type = 'Base Table'
AND table_name <> 'dtproperties'

OPEN curFixColsGetTables
FETCH NEXT FROM curFixColsGetTables into @TableName

WHILE @@FETCH_STATUS = 0
BEGIN
 
  DECLARE curFixColsGetCols CURSOR
  FOR SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH
  FROM information_schema.columns
  WHERE table_name = @TableName AND DATA_TYPE = 'nvarchar'

  OPEN curFixColsGetCols
  FETCH NEXT FROM curFixColsGetCols INTO @ColumnName, @ColumnLength
 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    SELECT @strSQL = 'ALTER TABLE ' + @TableName
           + ' ALTER COLUMN ' + @ColumnName
           + ' varchar(' + CAST(@ColumnLength AS VARCHAR(5)) + ')'
   
--  Run as is to see what fields are going to be change
PRINT @strSQL

--  Uncomment next line to commit changes
--  EXEC  SP_EXECUTESQL @strSQL

    FETCH NEXT FROM curFixColsGetCols
    INTO @ColumnName, @ColumnLength
  END
  CLOSE curFixColsGetCols
  DEALLOCATE curFixColsGetCols
 
  FETCH NEXT FROM curFixColsGetTables
  INTO @TableName
  END
CLOSE curFixColsGetTables
DEALLOCATE curFixColsGetTables

0
 
LVL 50

Expert Comment

by:Lowfatspread
ID: 10718241
thanks for sharing the solution.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Let's review the features of new SQL Server 2012 (Denali CTP3). It listed as below: PERCENT_RANK(): PERCENT_RANK() function will returns the percentage value of rank of the values among its group. PERCENT_RANK() function value always in be…
Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
Using examples as well as descriptions, and references to Books Online, show the documentation available for datatypes, explain the available data types and show how data can be passed into and out of variables.
Viewers will learn how to use the SELECT statement in SQL and will be exposed to the many uses the SELECT statement has.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question