I have a table in SQL Server 2008 database hosted on a shared web hosting. I cannot change the collation of the database because I don't have permissions.
When I created the table, I set the collation for the columns that I want but it doesn't do anything and I still see ???? when I query the table. I tried nvarchar as well and it didn't work.
The table:
CREATE TABLE [dbo].[T_Client]
(
[ClientID] [int] IDENTITY(1,1) NOT NULL,
[ClientName] [varchar](200) collate Hebrew_CI_AI null ,
[Address] [varchar](200) collate Hebrew_CI_AI null
)
You must ensure that the data is passed all the way to SQL Server using a format with compatible code points. Since you don't have Hebrew as your database or instance collation a varchar variable can't be used to store the data. So this
declare #d varchar(100) = 'שלום לך עולם' collate Hebrew_CI_AI
select #d
outputs
???? ?? ????
In this scenario you have to pass the value to the databse as NVARCHAR
declare #d nvarchar(100) = N'שלום לך עולם' collate Hebrew_CI_AI
select #d
You could use a varchar column with a Hebrew collation to store the data, but you should just use an nvarchar column. Still use the collation to produce the desired sorting and comparision semantics.
The problem is your INSERT/UPDATE statements. Unless you define those values as an nvarchar then the characters outside the databases collation will be lost. This means you need to declare your parameters as an nvarchar. As a result I would suggest, instead, not changing the collation of the columns and changing them as an nvarchar and using an nvarchars throughout your code.
Related
I have a problem when trying with Like statement like this:
First I have the data sheet:
When I execute the Sql command it does not do what I want.
My syntax:
select * from tbUsers where nUserID like N'%p%';
It does not show any results. Although I know that 'Finds any values that have' p 'in any position'
result picture:
my code to create table:
Create table tbUsers(
iIDUser int identity(1,1) not null primary key,
nUserID nvarchar(50) null,
nPassWord nvarchar(50) null,
dDate datetime null,
nName nvarchar(50) null
)
INSERT INTO tbUsers(nUserID,nPassword,nName) VALUES('phuc','123456', 'Phuc Nguyen')
INSERT INTO tbUsers(nUserID,nPassword) VALUES('ngocanh','123456')
INSERT INTO tbUsers(nUserID,nPassword) VALUES('long','123456')
INSERT INTO tbUsers(nUserID,nPassword) VALUES('long%ngocanh','123456')
INSERT INTO tbUsers(nUserID,nPassword) VALUES('phuc nguyen','123456')
Please help me. Thank you.
Hi your problem can be your collation if you need the Vietnamese collation for any reason you can alter your query to use the collation in your query like this one:
select *
from tbUsers
where nUserID collate SQL_Latin1_General_CP1_CI_AS like N'%p%';
If not my recommendation is to re-create the database using the collation SQL_Latin1_General_CP1_CI_AS since this query will be slow.
Also take in consideration if you have an index in the user column using double %% this will not let your index to be used. If you use only one % the index will be activated. Take a look of the execution plan to review this.
If want to stay with the Vietnamese collation maybe change the collation to the columns you need for this type of functionality. This will help you with the performance.
To change the collation of a column use
ALTER TABLE MyTable ALTER COLUMN Column1 [TYPE] COLLATE [NewCollation]
You can take a look to this question for more details
How to set collation of a column with SQL?
Since you are using Vietnamese collation you are not getting back the rows. You can specify the collation in your query quite easily though and it will return the rows you are looking for.
select *
from tbUsers
where nUserID collate SQL_Latin1_General_CP1_CI_AS like N'%p%';
The current database I'm using "PrimaryDatabase" has the collation "SQL_Latin1_General_CP1_CI_AS", while the "SecondaryDatabase" I'm trying to access has the collation "Arabic_CI_AS"
I changed the collation for the SecondaryDatabase and set it to " SQL_Latin1_General_CP1_CI_AS" and made sure it has been changed as well as in its tables.
However, when i run the query below I still get collation conflict.
select * from [MYSERVER].[SecondaryDatabase].[dbo].[SecondaryTableName]
where ltrim(rtrim([SecondaryTablename])) not in (select ltrim(rtrim(PrimaryFieldname)) from PrimaryTablename where PrimaryFieldName2=1)
One way to make your query work is to use COLLATE clause in order to apply a collation cast on both fields being involved in the predicate of the WHERE clause:
select *
from [MYSERVER].[SecondaryDatabase].[dbo].[SecondaryTableName]
where ltrim(rtrim([SecondaryFieldname])) COLLATE SQL_Latin1_General_CP1_CI_AS
not in (select ltrim(rtrim(PrimaryFieldname)) COLLATE SQL_Latin1_General_CP1_CI_AS
from PrimaryTablename
where PrimaryFieldName2 = 1)
The COLLATE clause applied to PrimaryFieldname might not be necessary, since this is the default collation of the corresponding database (so probably PrimaryFieldname already has this collation).
Another solution is to change the collation at field level, e.g.:
ALTER TABLE SecondaryDatabase
ALTER COLUMN SecondaryFieldname VARCHAR(50)
COLLATE SQL_Latin1_General_CP1_CS_AS NULL
I have a table with contents:
internalid foreignWord
1 បរិស្ថាន
2 ការអភិវឌ្ឍសហគមន៍
And its schema:
CREATE TABLE [dbo].[CE_testTable](
[internalid] [int] IDENTITY(1,1) NOT NULL,
[foreignWord] [nvarchar](50) NOT NULL
If I run:
SELECT TOP 1000 [internalid] ,[foreignWord] FROM CE_testTable where foreignWord = N'ការអភិវឌ្ឍសហគមន៍'
I get:
internalid foreignWord
1 បរិស្ថាន
2 ការអភិវឌ្ឍសហគមន៍
Which is both rows, it should have only returned the row with "ការអភិវឌ្ឍសហគមន៍" which is "community development" in Cambodian.
It is a NVARCHAR column and I'm selecting where N' etc? Any ideas?
Change the collation to Latin1_General_100_CI_AS.
You can specify collation for each column when you create the tables.
If you don't specify collation the columns will have the same collation that the database has.
CREATE TABLE [dbo].[CE_testTable](
[internalid] [int] IDENTITY(1,1) NOT NULL,
[foreignWord] [nvarchar](50) collate Latin1_General_100_CI_AS NOT NULL
)
SQL Fiddle
Try the query without the N
SELECT [internalid],
[foreignWord]
FROM CE_testTable
WHERE foreignWord = 'ការអភិវឌ្ឍសហគមន៍'
I seems like SQL Server can't do what I'm asking of it.
Looking at the comment from Erland Sommarskog, this explains my situation. It stores OK, and I can see the rows in there. But comparisons may fail. They did. So its a design level problem. I can't have different collations on the table, so I can't compare. For me this is not a problem it was only a PK that was erroring, I can work around.
Is it possible to have collate SQL_Latin1_General_CP1_CS_AS in table variable columns' definitions?
The reason I want to do this is because I have case sensitive information in my source table but when I insert it in the table variable there is a problem with the primary key (it is clustered) - duplicated values are detected - like 'All' and 'ALL'.
That's why I am trying to find a way to make the table variable columns case sensitive too as the following statement:
SELECT SERVERPROPERTY ('Collation')
gives me: "SQL_Latin1_General_CP1_CI_AS"
Yes it is possible. You can specify the collation for each column when you declare your table variable.
declare #T table
(
Col varchar(20) collate SQL_Latin1_General_CP1_CS_AS
)
Yes. It took something like 2 minutes to write the following script:
declare #T table (
ID int not null,
Val1 varchar(10) collate SQL_Latin1_General_CP1_CS_AS not null primary key
)
insert into #T(ID,Val1) values (1,'All'),(2,'ALL')
insert into #T(ID,Val1) values (3,'All')
Which first stored two rows, then errors on the second insert statement.
I have a SQL Server 2008 table which contains an external user reference currently stored as a bigint - the userid from the external table. I want to extend this to allow email address, open ID etc to be used as the external identifier. Is it possible to alter the column datatype from bigint to varchar without affecting any of the existing data?
Yes, that should be possible, no problem - as long as you make your VARCHAR field big enough to hold you BIGINT values :-)
You'd have to use something like this T-SQL:
ALTER TABLE dbo.YourTable
ALTER COLUMN YourColumnName VARCHAR(50) -- or whatever you want
and that should be it! Since all BIGINT values can be converted into a string, that command should work just fine and without any danger of losing data.