Reputation: 71
I have about 200 columns in my database with VARCHAR
type which is unable to store the rupee symbol. Now I have to change the datatype of all the columns from VARCHAR
to NVARCHAR
.
Can anyone please tell me the short way to accomplish this? And why does the VARCHAR
support the pound sign and not the rupee sign? I'm asking because I have to change the pound symbol to rupee symbol.
Upvotes: 7
Views: 10744
Reputation: 91
I met this issue today and Felix's answer worked quite well with one exception- if the column has default value defined. I researched a little bit and came up with the following script that drops and restores the default value.
Edited is_nullable line based on Fredrik's comment.
DECLARE @sql AS VARCHAR(MAX) = ''
SELECT @sql = @sql
+ CASE WHEN default_id>0 THEN 'ALTER TABLE '+table_name+' DROP CONSTRAINT '+OBJECT_NAME(default_id) +';'+CHAR(10) ELSE '' END
+ 'ALTER TABLE ' + table_name
+ ' ALTER COLUMN ' + column_name + ' NVARCHAR('
+ CASE WHEN (max_length <> - 1 AND max_length<4001) THEN CAST(max_length AS VARCHAR(10)) ELSE 'MAX' END + ')'
+ CASE WHEN is_nullable = 1 THEN '' ELSE ' NOT NULL' END
+ ';' + CHAR(10)
+ CASE WHEN default_id>0 THEN 'ALTER TABLE '+table_name+' ADD DEFAULT '+default_value+' FOR '+column_name +';'+CHAR(10) ELSE '' END
FROM (
SELECT
t.name AS table_name,
c.name AS column_name,
tp.name AS data_type,
c.max_length,
c.default_object_id AS default_id,
OBJECT_DEFINITION(c.default_object_id) AS default_value,
c.is_nullable
FROM sys.tables AS t
INNER JOIN sys.columns c
ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types tp
ON tp.user_type_id = c.user_type_id
WHERE tp.name = 'varchar'
)t
PRINT @sql
EXEC(@sql)
Upvotes: 5
Reputation: 89
Adding on to Felix Pamittan's answer if you need to include schema.
DECLARE @sql AS VARCHAR(MAX) = ''
SELECT @sql = @sql
+ 'ALTER TABLE ' + table_schema_name + '.' + table_name
+ ' ALTER COLUMN ' + column_name + ' NVARCHAR('
+ CASE WHEN max_length <> - 1 THEN CAST(max_length AS VARCHAR(10)) ELSE 'MAX' END + ')'
+ CASE WHEN is_nullable = 1 THEN ' NULL' ELSE '' END
+ ';' + CHAR(10)
FROM (
SELECT
sc.name AS table_schema_name,
t.name AS table_name,
c.name AS column_name,
tp.name AS data_type,
c.max_length,
c.is_nullable
FROM sys.tables AS t
INNER JOIN sys.columns c
ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types tp
ON tp.user_type_id = c.user_type_id
INNER JOIN sys.schemas sc
ON sc.schema_id = t.schema_id
WHERE tp.name = 'varchar'
)t
PRINT @sql
EXEC(@sql)
Upvotes: 1
Reputation: 23
Normally in sqlserver VARCHAR
datatype allows only the ANSI Characters, But NVARCHAR
allows UNICODE Character sets also, Pound symbol(156-ascii number), $ symbols are comes under ANSI character set.
So VARCHAR
allows those.
But when u comes to the Rupee Symbol its recently invented so it comes under UNICODE character set, to achieve the rupee symbol we need to use rupees font or glyphs...
Hope you understood y Pound comes under VARCHAR
and Rupee Comes under NVARCHAR
...
Upvotes: 1
Reputation: 1913
This will loop through all tables and their columns, and will generate query for updating those which have datatype as varchar
SET NOCOUNT ON
DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @Length nvarchar(128)
SET @TableName = ''
WHILE @TableName IS NOT NULL
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
BEGIN
SELECT @ColumnName=MIN(QUOTENAME(COLUMN_NAME)),@Length=MIN(CHARACTER_MAXIMUM_LENGTH)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2)
AND TABLE_NAME = PARSENAME(@TableName, 1)
--AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal')
AND DATA_TYPE IN ('varchar')
AND QUOTENAME(COLUMN_NAME) > @ColumnName
IF @ColumnName IS NOT NULL and @Length > 0
BEGIN
print (' ALTER TABLE ' +@TableName+ ' ALTER COLUMN ' + @ColumnName + ' NVARCHAR('+@Length+')')
--exec (@dSql)
END
END
END
Upvotes: 0
Reputation: 31879
You can view all the columns, their data types and the table they belong using the ff query:
SELECT
t.name AS table_name,
c.name AS column_name,
tp.name AS data_type,
c.max_length,
c.is_nullable
FROM sys.tables AS t
INNER JOIN sys.columns c
ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types tp
ON tp.user_type_id = c.user_type_id
WHERE tp.name = 'varchar'
From the query above, you want to generate a dynamic sql that will change all your VARCHAR
columns to NVARCHAR
.
DECLARE @sql AS VARCHAR(MAX) = ''
SELECT @sql = @sql
+ 'ALTER TABLE ' + table_name
+ ' ALTER COLUMN ' + column_name + ' NVARCHAR('
+ CASE WHEN max_length <> - 1 THEN CAST(max_length AS VARCHAR(10)) ELSE 'MAX' END + ')'
+ CASE WHEN is_nullable = 1 THEN ' NULL' ELSE '' END
+ ';' + CHAR(10)
FROM (
SELECT
t.name AS table_name,
c.name AS column_name,
tp.name AS data_type,
c.max_length,
c.is_nullable
FROM sys.tables AS t
INNER JOIN sys.columns c
ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types tp
ON tp.user_type_id = c.user_type_id
WHERE tp.name = 'varchar'
)t
PRINT @sql
EXEC(@sql)
Upvotes: 14
Reputation: 8865
SELECT 'ALTER TABLE' +QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME(TABLE_NAME)+ 'ALTER COLUMN ' + COLUMN_NAME + ' NVARCHAR(100)'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'TAbleName'
Upvotes: -1