Checking for empty xml column - sql

Next query runs successfully:
select top(100) * from PackageSessionNodes
where Cast(ContentInteractions as nvarchar) != ''
Next gives me error
Target string size is too small to represent the XML instance
update PackageSessionNodes set ContentInteractions = '<contentinteractions />'
where Cast(ContentInteractions as nvarchar) = ''
ContentInteractions is an xml column. No DDT defined on it.
How can I solve the second query so that I get those records with '' as xml?
I seems like SqlServer cannot deal with empty values that are stores in a xml column... but you can insert them... how's that?

The problem is with your CAST. When you don't specify the length of nvarchar, it defaults to 30 characters in the CAST-function. So what what your statement really says is
update PackageSessionNodes set ContentInteractions = '<contentinteractions />'
where Cast(ContentInteractions as nvarchar(30)) = ''
So if the XML-content of ContentInteractions is serialized to more than 30 characters, you get this problem.

Related

SQL: How to make a replace on the field ''

I have a very but tricky question for you guys. So, listen I have a field with spaces and numbers in one of my table columns. The key part is transform the content in a decimal field. The drawback is basically that for some rows I could get something like:
' 1584.00 '
' 156546'
'545.00 '
' '
So, to clean up my column, I have done a LTRIM and RTRIM so spaces gone. So now for a couple of records where the record were just spaces the new content is ''. Finally I need to convert this result to a decimal.
Issue: The thing is that for field that contend just the spaces the new result is '' and I'm not able to apply a REPLACE on this because it's a blank and the code below doesn't work:
SELECT REPLACE('','','0')
-- Final current verison
SELECT CAST(COALESCE(REPLACE(REPLACE([Gross_Weight],' ','0'),',',''),'0') AS DECIMAL(13,3))
How could I figure it out?
thanks so much
SELECT COALESCE(NULLIF(MyColumn, ''), 0)
This has the side-effect that you will also turn NULL values into 0, which you might not want. If that's a problem then a simple CASE statement should do the trick:
SELECT CASE WHEN MyColumn = '' THEN 0 ELSE CAST(MyColumn AS DECIMAL(10, 4)) END
Obviously you'll also have to incorporate any other manipulations that you're already doing.
No need for replace, just concatenate a zero to your column, like
SELECT RTRIM('0' + LTRIM(column))
I presume your data is in a table.
Lets call this table 'DATA' and the column 'VALUE'
Then you might use the below query
UPDATE DATA SET VALUE = 0 where VALUE = ''
To select the value do the below
select case ltrim(rtrim([Gross_Weight])) when ''
THEN 0
ELSE ltrim(rtrim([Gross_Weight])) END
Let me know if i get the requirement wrong.

Looping a CASE WHEN and REPLACE statement in SQL

Apologies for the multiple basic questions - I am very new to SQL and still trying to work things out.
I would like to insert records from my staging table to another table in my database, both removing the double quotes in the source file with a 'replace' function and converting the data from nvarchar (staging table) to datetime2. I can't quite work out how to do this: if I loop the 'case when' within 'replace', as below, then SQL doesn't recognise my data and nulls it out:
CASE WHEN ISDATE (REPLACE([Column1], '"', '')) = 1
THEN CONVERT(datetime2, Column1, 103)
ELSE null END
However if I loop my 'replace' within my 'case when', as below, SQL gives me an error message saying that it is unable to convert nvarchar into datetime2:
LTRIM(REPLACE([Column1], '"', '')
,CASE WHEN ISDATE(Column1) = 1 THEN CONVERT(datetime2, Column1, 103)
ELSE null END
What order / syntax do I need to be using to achieve this? An example of the data field would be:
"16/10/2017"
It uploads to my staging table as nvarchar
"16/10/2017"
and I would like to move it into my table2 as datetime2:
16/10/2017
Instead of isdate(), use try_convert():
TRY_CONVERT(datetime2, LTRIM(REPLACE([Column1], '"', ''), 103)
I think your confusion is that you need to do the string manipulation before the conversion. To do this, the string manipulation needs to be an argument to the conversion.
You are doing it right. The problem is, convert needs value without " ", and hence your convert was failing.
Just try this :
select
CASE WHEN ISDATE (REPLACE([Column1], '"', '')) = 1
THEN CONVERT(datetime2, (REPLACE([Column1], '"', '')), 103)
ELSE null END
from #tbl
more details : cast and convert doc

SQL UPPER only specific word

Does anyone know how I can change only a word in the varchar field in my database? They are formatted like "Cheese", "cheese", "CheesE". I want to change to them all to CHEESE, but I have other text in those fields as well. I was wondering if their was a way to single that word out and make it uppper.
Something like
update table
set field = Upper(cheese)+rest of field
Thanks
update table
set field = replace(field, 'cheese', 'CHEESE')
SQLFIddle demo
From your comments I can see the diference between substring and word.
It is possible to do this kind of 'word-centric' transformation using XML as a proxy format.
Try this...
DECLARE #pattern nvarchar(max) = 'cheese'
SELECT
converted =
cast('<a><i>' + REPLACE(field, ' ', '</i><i>') + '</i></a>' as xml)
.query(
'for $x in /a/i return
if (not( ($x) is (/a/i[last()])[1] )) then
if (data($x) = sql:variable("#pattern")) then
concat(upper-case($x), "")
else
concat($x, "")
else
if (data($x) = sql:variable("#pattern")) then
string(upper-case($x))
else
string(data($x))')
.value('.', 'nvarchar(max)')
FROM table
I'm sure that it's possible to do it by parsing the expression char-by-char but I wanted to try it with XML :)

Why variable with nvarchar(max) work incorrect

Currently, I have a function to get list of columns of 1 table with detail attribute. And off course, there are some tables with a lot of columns. So, the output will be over 10.000 characters.
Here I test like this:
declare #aa nvarchar(max)
set #aa = dbo.fnGetColumnList('Table_Name')
print #aa
The result always has around 4000 characters. It looks like the SQL has truncated it.
What I know that when we declare nvarchar(max), SQL will supports up to 2^32-1 (2GB) for this string. But why it just has around 4000 characters?
When I execute like this:
select dbo.fnGetColumnList('Table_Name')
the result is correct.
And here is the code for the function:
-- get column list from table Mapping
ALTER FUNCTION [dbo].[fnGetColumnList] ( #tblName varchar (30))
RETURNS nvarchar(max)
AS
BEGIN
Declare #sql nvarchar(max)
set #sql = ''
SELECT #sql = #sql + case
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' ('+convert(varchar(10),[Length])+') NULL' + CHAR(13)
when CHARINDEX('char', LOWER([DBType])) > 0 then ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
ELSE ', ['+[DBColumn]+']' + ' ['+[DBType]+']' + ' NULL' + CHAR(13)
end FROM dbo.Mapping WHERE [DBTable] = #tblName
return #sql
END
Please advance.
This is almost always a variable assignment type problem, as explained in:
For Nvarchar(Max) I am only getting 4000 characters in TSQL?
If it's not that, then it's probably just the settings of Print to display too few characters:
nvarchar(max) still being truncated
Having looked at the updated code, it seems like it's the second issue, your print is truncating as it's not set to show enough characters.
You should see this by running
SELECT LEN(#aa)
You'll get a number larger than 4000, showing the value is held correctly in the variable.
As explained in Microsoft's nvar and nvarchar docs:
A common misconception is to think that with nchar(n) and nvarchar(n), the n defines the number of characters. However, in nchar(n) and nvarchar(n), the n defines the string length in byte-pairs (0-4,000). n never defines numbers of characters that can be stored. This is similar to the definition of char(n) and varchar(n).
There is an option in SQL Management Studio:
Tools > Options... > Query Results > SQL Server > Results to Text > Maximum number of characters displayed in each column

How can I truncate results after a certain amount of characters in SQL Server

I'm trying to truncate results after 32,759 characters, since that is the character limit in excel and that's where my results will be pasted.
Two method I've tried so far:
CONVERT(varchar(max), substring(comment,1,37259)) as [Comment]
CONVERT(varchar(max), ( substring(comment,1,8000) + substring(comment,8001,16000)...)) as [comment]
Edit: It seems like the data isn't getting into the varchar(max) as it's returning results with only 8000 characters. This is part of a select statement. I have no problem getting results over 32759 characters, it's just that they run into the next line when pasting into excel - which is why I'm trying to truncate.
Figured it out, might as well toss this up in case someone else runs into this problem:
convert(varchar(max), ( cast(substring(comment,1,8000) as varchar(max)) +
cast(substring(comment,8001,8000) as varchar(max)) +
cast(substring(comment,16002,8000) as varchar(max)) +
cast(substring(comment,24003,8000) as varchar(max)) +
cast(substring(comment,32004,755) as varchar(max)) )) as
[comment]
It looks like by not casting each piece the data size is being set to a data size/type that will accommodate all pieces.
All this stuff shouldn't be necessary. If comment is varchar(max), you should be able to say:
SUBSTRING(comment, 1, 37259)
If it is text or ntext then you need to convert it first:
SUBSTRING(CONVERT(VARCHAR(MAX), comment), 1, 37259)
(Which is obviously much tidier than your solution.)