Category: SQL

The data type ntext cannot be used as an operand to the UNION, INTERSECT or EXCEPT operators because it is not comparable.

Exception Message

With today’s post, we will deep dive into an error message that one of my friend encountered recently as below.
The data type ntext cannot be used as an operand to the UNION, INTERSECT or EXCEPT operators because it is not comparable.
Sample Code

Let us first replicate the issue with the below sample code snippet.
Drop Table  if exists T1,T2
create Table T1(id int,Col1 ntext)
Create Table T2(id int,Col1 ntext)

Insert into T1 Values(1,'Big value')
Insert into T2 Values(1,'Big value')

Select  * From (
Select * From T1
union 
Select * From T2)A

The execution of the above code results in the error message and the message is very clear that those specified operators are not allowed with ntext datatype.

Solution

1. Avoid NTEXT datatype

NTEXT datatype is a deprecated datatype in SQL Server. Try to avoid in future development and replace the existing with nvarchar(max).

2. Replace UNION with UNION ALL (if possible)

UNION ALL is a clear winner of this situation over UNION operator. So, if you can change the code to replace union with union all, that would be the easiest way. Then why is it so? – Simple, UNION operator does a sort operation internally which is forbidden with datatype ntext whereas UNION ALL does not require sort operation.

Select  * From (
Select * From T1
union ALL
Select * From T2)A

3. Construct column list without ntext datatype columns

Drop Table  if exists T1,T2
create Table T1(id int,Col1 ntext)
Create Table T2(id int,Col1 ntext)

Insert into T1 Values(1,'Big value')
Insert into T2 Values(1,'Big value')

--Construction of column list without ntext datatype columns

Declare @Col_list varchar(max)
Set @Col_list = (
SELECT  STUFF((SELECT  ',' + name FROM sys.columns EE
            WHERE   EE.object_id =E.object_id and system_type_id not in (99)
            ORDER BY column_id 
        FOR XML PATH('')), 1, 1, '') AS 'CommaseparatedString'
FROM sys.columns E where object_id = object_id('T1') 
and system_type_id not in (99) group by object_id) 

Declare @sql nvarchar(max) = ''
Set @sql = 'Select  * From (
Select ' + @Col_list + ' From T1
union
Select ' + @Col_list + ' From T2)A'

exec sp_executesql @sql

Sometime, we may not be able to avoid the ntext column depending on the requirement. In such situation, you may use an explicit conversion of those ntext datatype to nvarchar(max) as below.

--Construction of column list with ntext datatype columns but with explicit conversion of datatype

Declare @Col_list varchar(max)
Set @Col_list = (
SELECT  STUFF((SELECT  ',' + case when system_type_id= 99  then 'Cast(' +  name + ' as nvarchar(max)) as ' + name Else name End FROM sys.columns EE
            WHERE   EE.object_id =E.object_id 
            ORDER BY column_id 
        FOR XML PATH('')), 1, 1, '') AS 'CommaseparatedString'
FROM sys.columns E where object_id = object_id('T1') 
group by object_id) 

I’d like to grow my readership. If you enjoyed this blog post, please share it with your friends!

Can NEWID() generate duplicate value in SQL Server?

Earlier, I blogged on updating table with random numbers in SQL Server, later one of my friend asked me how guarantee that NEWID() can NOT generate duplicate value in SQL Server? The question seems to be a very valid and tried to find an answer for the same and here is the excerpt & explanation of my analysis and findings.

The NEWID function in Microsoft SQL Server Transact-SQL returns standard random version-4 UUIDs, while the NEWSEQUENTIALID function returns 128-bit identifiers similar to UUIDs which are committed to ascend in sequence until the next system reboot. A version 4 UUID is randomly generated. As in other UUIDs, 4 bits are used to indicate version 4, and 2 or 3 bits to indicate the variant (102 or 1102 for variants 1 and 2 respectively). Thus, for variant 1 (that is, most UUIDs) a random version-4 UUID will have 6 predetermined variant and version bits, leaving 122 bits for the randomly generated part, for a total of 2122, or 5.3×1036 (5.3 undecillion) possible version-4 variant-1 UUIDs.


The important excerpt from the screenshot is – “the probability to find a duplicate within 103 trillion version-4 UUIDs is one in a billion.”

Just a bit on algorithm used for version 4 as below. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers. The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers.

The algorithm is as follows:

o Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively.

o Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to the 4-bit version number from Section 4.1.3.

o Set all the other bits to randomly (or pseudo-randomly) chosen values.

Long story in short: NEWID() can generate duplicate value, however, the probability is one in a billion which is very negligible.

References
https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
https://tools.ietf.org/html/rfc4122

I’d like to grow my readership. If you enjoyed this blog post, please share it with your friends!

Microsoft SQL Server – Beginners Guide

Introduction:

This blog aims beginners on how easily they can learn SQL Server step by step. We are trying to cover most of the topics in a simple way with lots of examples and necessary explanations. Hope you will enjoy this series and feel free to share the feedback in comment section.

Audience:

This tutorial is designed for all those readers who want to learn the fundamentals of SQL Server and put it into practice. For beginners, it helps a step by step or stairway to learn SQL Server an d for advanced and experienced, it helps to refresh the points with examples.

Prerequisites:

As this is designed for beginners, there are only two prerequisites are expected.

1. Interest to learn SQL Server

2. If you have experience in other programming language, sometimes you may need to unlearn few things and learn new things to better understanding the concepts of database management.

It is good to have SQL Server installed on your computer, as it might assist you in executing the examples yourself and get to know how it works.

Table of contents:

Microsoft SQL Server – A bit of History & Introduction

A bit of History & Introduction

SQL Server – System Databases

  1. Master
  2. Msdb
  3. Model
  4. TEMPDB

SQL Server – Constraints

Constraints in SQL server defines the rules and restrictions to a column or multiple columns that enforces the integrity and reliability of the data in the specified column(s). Constraints can be defined at column level or table level in SQL Server. It can be specified while creating a table or even later time. However, once the constraints are specifying for an existing column, it will validate the rule defined by the constraints on the existing data. There are different types of constraints as below.

SQL Server – String Functions

SQL Server – Global Variables

Global variables have values set by the database server.  Users cannot create global variables, and cannot update the values of global variables directly. There are two type global variables – connection specific & server specific. eg: @@identity holds connection-specific information, Otherwise, variables such as @@connections, have values that are common to all connections. Let us quickly see some of global variables as below.

SQL Server – Date Time Functions

SQL Server – Window Functions

SQL Server – System Functions

SQL Server – Number Functions

SQL Server – System Procedures

SQL Server – Other Topics

I’d like to grow my readership. If you enjoyed this blog post, please share it with your friends!

Differences between ISNULL and COALESCE functions in SQL Server

This blog post explains ISNULL and COALESCE functions in SQL Server in a very simple way with examples. We would also cover some of major differences between these two system functions.

ISNULL()

Syntax : ISNULL(check_ValOrExp, replace_ValOrExp)

COALESCE()

Syntax : COALESCE(check_ValOrExp1, check_ValOrExp2,…, replace_ValOrExp)

COALESCE validates the list of check_ValOrExp and if it finds first non NULL value then it uses as the output else replaces with replace_ValORExp.

COALESCE is equivalent to :
	CASE WHEN check_ValOrExp1 IS NOT NULL THEN check_ValOrExp1 
		WHEN check_ValOrExp2 IS NOT NULL THEN check_ValOrExp2 
		...
		...
	ELSE replace_ValOrExp END 

That means, this is how SQL Server is resolving internally while performing ISNULL function. To me, COALESCE is a beautified format of CASE WHEN…ELSE END.

Differences between ISNULL & COALESCE

1. Query execution & evaluation method

ISNULL function evaluates the check_ValOrExp as below:

	If check_ValOrExp is NOT NULL it returns check_ValOrExp (Return type is the same as type of check_ValOrExp)
	If check_ValOrExp is NULL then 
		If replace_ValOrExp is NOT NULL it returns replace_ValOrExp (Return type is the same as type of check_ValOrExp) 
	        Else if replace_ValORExp is null then it returns NULL (Return type is int) 

COALESCE evaluates the check_ValOrExp as below: Its similar to ISNULL, however, it does the evaluation until it finds first NON NULL value from Left to right defined fields in COALESCE. It is very important to be noted that, If check_ValOrExp is another query then it has to execute twice; one for checking the expression and the other for assignment part. Let us look at this behavior from execution plan from a very simple query for everyone to understand better.
Select isnull(Parenttable,'NA'),coalesce(ParentTable,'NA') From TableName
Execution Plan (XML format) snapshot: So, depending on your isolation level, you might end up with unexpected results. So, I personally tried to avoid COALESCE for validating any subquery/corelated query outputs. Otherwise, we might need to handle it differently to run the sub query only once.

In one sentence – ISNULL is a function but COALESCE is an Expression in SQL Server.

2. Return Datatype

ISNULL function returns the datatype of the first parameter.

COALESCE returns the data type of value with the highest precedence.
Declare @Param1 varchar(1) = NULL
Select isnull(@Param1 ,'NA') IsnullVal,coalesce(@Param1 ,'NA') CoalesceVal

3. Input Parameters

ISNULL function needs ONCE and ONLY two parameters. Whereas COALESCE can have variable number of parameters. (Technically, I would not call this as input parameters since COALESCE is not a function.)

4. NULLability of result

The ISNULL return value is always considered NOT NULLable. By contrast,COALESCE with non-null parameters is considered to be NULL. Micorosoft has provided a very good example, nothing to beat with a better one as below.

This statement fails because the PRIMARY KEY cannot accept NULL values and the nullability of the COALESCE expression for col2 evaluates to NULL.

CREATE TABLE #Demo   
(   
  col1 INTEGER NULL,   
  col2 AS COALESCE(col1, 0) PRIMARY KEY,   
  col3 AS ISNULL(col1, 0)   
);   

This statement succeeds because the nullability of the ISNULL function evaluates AS NOT NULL.

CREATE TABLE #Demo   
(   
  col1 INTEGER NULL,   
  col2 AS COALESCE(col1, 0),   
  col3 AS ISNULL(col1, 0) PRIMARY KEY   
);  

Hope you enjoyed this post, share your feedback in comment section. Recommending to go through “Microsoft SQL Server – Beginners Guide” series for more information.

I’d like to grow my readership. If you enjoyed this blog post, please share it with your friends!