Requires A Singleton?

Facebooktwitterredditpinterestlinkedinmail

Have you ever got this error message when you tried to parse an XML string in SQL Server?

XQuery [value()]: ‘value()’ requires a singleton (or empty sequence), found operand of type ‘xdt:untypedAtomic *’

DECLARE	@XMLToParse  XML
 
-- Load the XML data in to a variable to work with.
-- This would typically be passed as a parameter to a stored proc
SET		@XMLToParse =	'
								Baboon
						 '

SELECT	
@XMLToParse.value('data(/Animal/AnimalName)', 'VARCHAR(MAX)') AS AnimalName

 
How do we fix this?

This error is saying that the value() function needs an xpath that only exits once (non-repeating node). You and I know that there will only be one instance of , but SQL Server does not know that. To solve this, we just need to tell SQL Server that it should use the first instance of this AnimalName node that it finds. We do this by added the [1] tag to the xpath. We want to add it after the closing parentheses. This will tell SQL Server to grab whatever is the first node with that name.

DECLARE	@XMLToParse  XML
 
-- Load the XML data in to a variable to work with.
-- This would typically be passed as a parameter to a stored proc
SET		@XMLToParse =	'
								Baboon
						 '

SELECT	
@XMLToParse.value('data(/Animal/AnimalName)[1]', 'VARCHAR(MAX)') AS AnimalName
-- Notice the [1] on the line above!

 
Extra Fun

If there are multiple nodes with the same name in your XML, you can adjust the number inside the square braces to match whatever node you want. For example:


	Baboon
	Cat
	Dog 

[1] would return Baboon
[2] would return Cat
[3] would return Dog

If Statement In An Update

Facebooktwitterredditpinterestlinkedinmail

If you are updating multiple rows in one statement, but only want to update a value in a column if a condition is satisfied, then you need to perform some sort of if logic inside your update. Here’s a straight forward way of doing this.

In the example below, I am just going to use 2 temp table variables. I’ll update the @SourceTable with the data from the @UpdateTable… but only where the UpdateFlag field is set to 1.

DECLARE @SourceTable TABLE
(AnimalID INT,
 AnimalName VARCHAR(255))
 
DECLARE @UpdateTable TABLE
(AnimalID INT,
 UpdateToValue VARCHAR(255),
 UpdateFlag  BIT)
 
INSERT
INTO   @SourceTable
VALUES (1, 'Dog'),
       (2, 'Cat'),
       (3, 'Snake')
 
INSERT
INTO    @UpdateTable
VALUES  (1, 'Pig', 1),
        (2, 'Cow', 0),
        (3, 'Turkey', 1)

UPDATE  S
SET     S.AnimalName =	CASE WHEN U.UpdateFlag = 1 THEN U.UpdateToValue 
							 ELSE S.AnimalName 
						END
FROM    @SourceTable S
INNER   JOIN @UpdateTable U ON U.AnimalID = S.AnimalID

SELECT *
FROM   @SourceTable S

 
In the example above, you can see that the AnimalName is only updated when the UpdateFlag column is set to 1. The 2nd record “Cat” is not updated with the value “Cow” because it has a 0 for the UpdateFlag. This is done using a case statement on the SET operation. The example above is very simple. This case logic in the SET operation becomes much more helpful in more complex queries.

SQL Server Minus Operator

Facebooktwitterredditpinterestlinkedinmail

The MINUS operator is an Oracle operator and does not exist in SQL Server. SQL Server has its own operator that does this called EXCEPT. The usage of these two operators are the same between Oracle and SQL Server.

 
The EXCEPT Operator
The EXCEPT operator will take two queries and only show the records in the first query that do not exist in the second query. Here is an example of how this would work.

SELECT	A.AnimalName,
		AT.AnimalTypeName
FROM	Animal A
INNER	JOIN AnimalType AT ON AT.AnimalTypeID = A.AnimalTypeID

EXCEPT

SELECT	EA.AnimalName,
		AT.AnimalTypeName
FROM	ExtinctAnimal EA
INNER	JOIN AnimalType AT ON AT.AnimalTypeID = EA.AnimalTypeID

 
The above query will show all the animals from the Animal table where the animals are not in the ExtinctAnimal table.

 
 
Reference: https://msdn.microsoft.com/en-us/library/ms188055.aspx

What Is ANSI_PADDING

Facebooktwitterredditpinterestlinkedinmail

If you work with stored procedures or if you script objects in SQL Server, you have probably seen SET statements that turn on/off some crazy thing called ANSI_PADDING. If you’re like most people, you just ignore this because it works. I wanted to take a few minutes to explain what this ANSI_PADDING thing is.

 
What Is ANSI_PADDING?
ANSI_PADDING is an option that controls how VARCHAR and VARBINARY values are stored. If ANSI_PADDING is turned on, then SQL Server will NOT trim the trailing spaces when it inserts into a VARCHAR field. Similarly, it will NOT trim trailing nulls when it inserts into a VARBINARY field.

 
Setting the ANSI_PADDING only affects the spaces on inserts. It does NOT affect comparisons.

Syntax For Setting The ANSI_PADDING:

SET	ANSI_PADDING ON
GO

INSERT
INTO	Animal
	(AnimalName)
VALUES	('Dog    ')

GO

SET	ANSI_PADDING OFF
GO

LIKE in SQL

Facebooktwitterredditpinterestlinkedinmail

The LIKE operator in SQL Server allows you to query data using patterns instead of exact matches. Normal select statements using the = operator will only return records where there is an exact match (usually the casing or trailing spaces do not matter). With the LIKE operator, it does not need to be an exact match.

LIKE
The most basic concept of the like operator is that it allows you to query data without using an exact match in the WHERE clause. It allows you to use some wildcard characters to get the results you are looking for. Here is a basic example:

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE 'Giant %'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
35,Giant Squid,Fish,400
36,Giant Panda,Mammal,500
37,Giant Clam,Fish,60
[/table]

The above statement uses the % as a wildcard. It basically says, show me any animals that start with the word Giant. This would return things like Giant Panda, Giant Squid, and Giant Clam.

Although % is the most common wildcard that is used with LIKE, there are many more. Here is a list of all the allowed wildcards.

%
Will allow zero or any characters. You can use this before, after, or in-between any string.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE 'GIANT %'
	OR AnimalName LIKE '% Penguin'
	OR AnimalName LIKE 'Hammer% Shark'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
35,Giant Squid,Fish,400
36,Giant Panda,Mammal,500
37,Giant Clam,Fish,60
38,Emperor Penguin,Bird,15
39,Hammer Head Shark,Fish,90
[/table]

 
_
Will allow any 1 character.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE 'Chicke_'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
18,Chicken,Bird,5
[/table]

 
[]
Will allow 1 character that is specified in the brackets. There are two ways to specify this. [a-d] or [abcd].

The following example will match both goose and moose.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE '[gm]oose'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
11,Goose,Bird,15
27,Moose,Mammal,1000
[/table]

 
The following example will match both cat and bat, but it will NOT match rat.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE '[a-d]at'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
10,Cat,Mammal,10
34,Bat,Bird,1
[/table]

 
[^]
Will match any 1 character that is NOT specified in the brackets. There are two ways to specify this. [^a-d] or [^abcd].

The following example will match horse, but will NOT match zorse… and yes, zorse is an animal… I found it on the internet.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE '[^z]orse'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
6,Horse,Mammal,750
[/table]

 
The following example will match rat, but will NOT match bat or cat.

SELECT	*
FROM	Animal
WHERE	AnimalName LIKE '[^a-d]at'

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
AnimalID,AnimalName,AnimalType,Animal Weight
33,Rat,Mammal,1
[/table]

 
Important
If you are comparing a CHAR data type with the like operator, it may not work correctly. This because when you save data to a CHAR field it will space pad the field to the size of the field. To get around this, you need to trim the spaces from the end of the field.

SELECT	*
FROM	Animal
WHERE	RTRIM(AnimalName) LIKE '%monkey'

 
NOT Like
If you want to match where a pattern is NOT like a string, simply put the word NOT in front of the word LIKE.

SELECT	*
FROM	Animal
WHERE	AnimalName NOT LIKE ‘%monkey’

 
 
Escaping The Wildcard
From time to time you will need to actually search for a pattern containing one of the wildcard characters. Let’s say that you wanted to search for anything in a string that had 10% in it. The % (percent symbol) is a reserved word with the LIKE operator. You would search for the % character by using the ESCAPE clause.

SELECT	*
FROM	Invoice
WHERE	LineItemDescription LIKE '10!%%' ESCAPE '!'

In the query above, you can see that !% in the comparison string means to the literal character %. The ESCAPE clause tells the query to not apply the wildcard rules to any character following the specified characters. In this case, we are specifying the ! (exclamation mark).

[table width=”500″ colwidth=”20|100|50″ colalign=”left|left|center|left|right”]
InvoiceID,ItemName,LineItemDescription
1,Coupon Code,10% off web coupon
[/table]

 
Reference: https://msdn.microsoft.com/en-us/library/ms179859.aspx