I'm using Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64)
Aug 22 2017 17:04:49
Copyright (C) 2017 Microsoft Corporation
Developer Edition (64-bit) on Windows Server 2012 R2 Standard Evaluation 6.3 <X64> (Build 9600: ) (Hypervisor)
When i do: INSERT INTO MYTABLE(COLNAME) VALUES ('Қазақстан') it inserts question marks ????????? instead of actual string. My column type is NVARCHAR(255). If i insert N character before my value like this: ...(N'Қазақстан') it will be persisted properly. Is it the only way to insert non-ASCII characters or should i change something else?
Thanks!
The answer to your question is Yes, you should use N
From Docs
When prefixing a string constant with the letter N, the implicit conversion will result in a UCS-2 or UTF-16 string if the constant to convert does not exceed the max length for the nvarchar string data type (4,000). Otherwise, the implicit conversion will result in a large-value nvarchar(max).
So if you don't use N then SQL Server will treate it as VARCHAR (non unicode).
Using the N will convert the string to unicode string.
Related
Any idea why the two hashing functions in SQL Server and Oracle yield different results when hashing the non-breaking space character?
Oracle select standard_hash('a ', 'MD5') from dual; results in 25EF28EB5A5BE667C6222418E9E27E8E and doesn't match SQL select HASHBYTES ('MD5','a '); results in CE8F03020C81133B3A082F8051EB9FF6. Note the space after the input 'a' is a non-breaking space character.
Is there any good source that can lay out the differences?
This appears to be a character set or "collation" issue, where Oracle is in UTF-8 and SQL Server is in Latin 1252. My solution was to CONVERT the value to Windows Latin-1252 in Oracle before calculating the hash: select STANDARD_HASH(CONVERT('a ','WE8MSWIN1252'), 'MD5') from dual.
To find my collation/character set I did SELECT collation_name FROM sys.databases WHERE name = 'MY_DB_NAME'; in SQL Server and select * from nls_database_parameters where parameter='NLS_CHARACTERSET'; in Oracle.
First of all you need to establish which one is actually yielding "different" results:
Using your favourite search engine to find online hash generators and testing results.
External Resources
https://passwordsgenerator.net/md5-hash-generator/ - 99020CB24BD13238D907C65CC2B57C03
https://www.md5hashgenerator.com/ - 99020cb24bd13238d907c65cc2b57c03
https://www.miraclesalad.com/webtools/md5.php - 99020cb24bd13238d907c65cc2b57c03
SQL Server
select HASHBYTES ('MD5', 'a ')
SQL Server 2014 SP3 (12.0.6024.0) - 0x99020CB24BD13238D907C65CC2B57C03
SQL Server 2019 (15.0.2080.9) - 0x99020CB24BD13238D907C65CC2B57C03
Oracle (using https://dbfiddle.uk/)
select standard_hash('a ', 'MD5') from dual;
Oracle 21c - 0x99020CB24BD13238D907C65CC2B57C03
Oracle 18c - 0x99020CB24BD13238D907C65CC2B57C03
Oracle 11gR2 - "ORA-00904: "STANDARD_HASH": invalid identifier"
Conclusion
You can see that your Oracle produced answer differs even from other Oracle answers. What version of Oracle are you running? What other options are set, such as collation etc.?
Why does Server ignore the ₾ symbol ?
Why this:
print iif(N'₾' = N'', 'true', 'false')
is the same as:
print iif(N'₾2' = N'2', 'true', 'false')
What role does collation play in this situation and what is happening under the hood?
It looks to me that this is an issue related to the Unicode version when the character was introduced and the type of SQL Server collation that is used:
The € character was introduced in Unicode 2.1 and it returns false in all collations
The ₭ character was introduced in Unicode 3.0 and it returns false in the old collations (for example Latin1_General_CI_AS), but it returns true in the collations introduced in SQL Server 2008 (for example Latin1_General_100_CI_AS)
The ẞ character was introduced in Unicode 5.1 and it returns true in most collations, but it returns false in the collations introduced in SQL Server 2017 (for example Japanese_Bushu_Kakusu_140_CI_AS_VSS)
The ₸ character was introduced in Unicode 5.2 and it returns true in all collations (except BIN collations)
The ₾ character was introduced in Unicode 8.0 and it returns true in all collations (except BIN collations)
I'm using SQL Server 2016 (free version). The date camp is set to "yyyymmdd" but I would like that the data can be store in the table like "mmddyyyy".
What can I do ?
or this using format and cast (to make sure that it's of date data type)
select format(cast(#date as date),'MMddyyyy')
-- Syntax for SQL Server, Azure SQL Database, Azure SQL Data Warehouse,
SET DATEFORMAT { format | #format_var }
Arguments
format | #format_var
Is the order of the date parts. Valid parameters are mdy, dmy, ymd, ydm, myd, and dym. Can be either Unicode or double-byte character sets (DBCS) converted to Unicode. The U.S. English default is mdy.
I'm writing a little script to extract the password hashes of SQL Logins on 2008 and 2012 instances. Part of my code looks like this...
SELECT CONVERT (VARCHAR(514), (SELECT CAST (LOGINPROPERTY('sa', 'PasswordHash') AS varbinary(256))), 2)
When I run this in a 2012 instance, it all works fine. But when run on a 2008 instance I get a blank result. I've checked that the SQL login is valid and has a password on the 2008. The online documentation tells me that all the functions are valid between both versions.
What is the difference between the versions?
Regards,
JC
Hash algorythms used:
SQL Server 2012 and above use SHA2-512 (512 bytes hash)
SQL Server 2000 to 2008 R2 use SHA1 (160 bytes hash)
You can also uses this query and DMV:
Select password_hash, * From sys.sql_logins Where name in ('sa')
It gives the same hash that this query:
Select CONVERT (varchar(512), (LOGINPROPERTY('sa', 'PasswordHash') ), 2)
Use this one if you want a varchar starting with 0x
Select CONVERT (varchar(514), (LOGINPROPERTY('sa', 'PasswordHash') ), 1)
I am trying to update a table I have with the windows version of a SQL Server using ##VERSION. When I run SELECT ##VERSION I get
Microsoft SQL Server 2012 - 11.0.5058.0 (X64)
May 14 2014 18:34:29
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
AND in this case I want "Windows NT 6.3" (14 characters long) that will never change I always want the 14 characters "Windows NT (some version)".
Sometime when I query some servers the "(Hypervisor)" Isn't there or the parentheses and text after those 14 characters is different. I want to automate this and I need to find a way to pull out just "Windows NT (some version)".
charindex() lets you find the location of substrings within a string. It also let's you specify a third argument to begin the search in the middle of the string which allows us to find a match relative to another location. We'll use that function several times.
We need to know the start of our desired string and the end of it. So we anchor our search to the string "Windows NT " which is 11 characters long. Then we want to find the next space character immediately following that match. It's necessary to add 11 to that value so it doesn't find the space characters inside the anchoring match (before and after the "NT".)
charindex('Windows NT ', ##version) /* start of match */
charindex(' ', ##version, charindex('Windows NT ', ##version) + 11) /* end of match */
Those two expressions identify the string offset but substring() needs to know the length to extract which means it needs to know the difference between the offsets. Since we don't want the final space character in the return value there's no need to add one to include it.
substring(
##version,
charindex('Windows NT ', ##version),
charindex(' ', ##version, charindex('Windows NT ', ##version) + 11)
- charindex('Windows NT ', ##version)
)
If you know it will always be Windows, you can use that fact to search where "on Windows" is in that string since it should always only ever be present once. Once you know the starting position you can use substring and adjust the parameters such that the string "on " is removed and then just pull your 14 characters.
IE:
declare #str varchar(500) = 'Microsoft SQL Server xxx (SPy) - 10.0.5500.0
(X64)
Sep 21 2011 22:45:45
Copyright (c) 1988-2008 Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack
1) (VM)
'
select #str
select SUBSTRING(#str, CHARINDEX('on Windows', #str,1) + 3 ,14)