How Do I Escape Apostrophes in Field Valued in SQL Server? - sql

I asked a question a couple days ago about creating INSERTs by running a SELECT to move data to another server. That worked great until I ran into a table that has full on HTML and apostrophes in it. What's the best way to deal with this? Lucking there aren't too many rows so it is feasible as a last resort to 'copy and paste'. But, eventually I will need to do this and the table by that time will probably be way too big to copy and paste these HTML fields.
This is what I have now:
select 'Insert into userwidget ([Type],[UserName],[Title],[Description],[Data],[HtmlOutput],[DisplayOrder],[RealTime],[SubDisplayOrder]) VALUES ('
+ ISNULL('N'''+Convert(varchar(8000),Type)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),Username)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),Title)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),Description)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),Data)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),HTMLOutput)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),DisplayOrder)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),RealTime)+'''','NULL') + ','
+ ISNULL('N'''+Convert(varchar(8000),SubDisplayOrder)+'''','NULL') + ')'
from userwidget
Which is works fine except those pesky apostrophes in the HTMLOutput field. Can I escape them by having the query double up on the apostrophes or is there a way of encoding the field result so it won't matter?

You can replace the single apostrophe with double apostrophes.
ISNULL('N'''+ REPLACE(Convert(varchar(8000),Type), '''', '''''') + '''','NULL') + ','

You should use parameters instead of injecting values into your SQL query.

Use QUOTENAME function
declare #valueAsNull as varchar(10)
set #valueAsNull = quotename('NULL','''')
SELECT 'Insert into userwidget ([Type],[UserName],[Title],[Description],[Data],[HtmlOutput],[DisplayOrder],[RealTime],[SubDisplayOrder]) VALUES (' +
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(Type,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(Username,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(Title,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(Description,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(Data,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(HTMLOutput,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(DisplayOrder,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(RealTime,'NULL'),''''), #valueAsNull,'NULL') + ', '
REPLACE(QUOTENAME(Convert(varchar(8000),ISNULL(SubDisplayOrder,'NULL'),''''), #valueAsNull,'NULL') + ')'
FROM userwidget

Related

How to get the Column Header for the SQL select query with Pipe delimited

I written an SQL Server select Query with Format "|" delimited but I did not get the column Name Header only value is printing. I am new in SQL server tried different way as column alias but it not worked out.
Please help on this.
SELECT ID + '|'
+ LTL + '|'
+ Safely + '|'
+ Dock + '|'
+ Required + '|'
+ Hours + '|'
+ Dock + '|'
+ Jack + '|'
+ Dolly + '|'
+ convert(varchar(100), Pallets) + '|'
+ convert(varchar(100), wgPallets) + '|'
+ convert(varchar(100), NoBoxes) + '|'
+ convert(varchar(100), WgBoxes) + '|'
+ convert(varchar(100), Cabinets) + '|'
+ convert(varchar(100), Racks) + '|'
+ Batteries + '|'
+ Sited + '|'
+ convert(varchar(23),Date_Enter,121) + '|'
FROM sales
How to display the coulmn Header as below along with with value using above query.
ID|LTL|Safely|Dock|Required|Hours|Dock|Jack|Carrier_Dolly|Pallets|WgPallets|NoBoxes|WgBoxes|Cabinets|Racks|Batteries|Sited|Date_Enter
Thanks in Advance
If you want your headers to appear as result line in your SQL you have to tell SQL engine so.
This can be done with a UNION:
SELECT
'ID|LTL|Safely|Dock|Required|Hours|Dock|Jack|Carrier_Dolly|Pallets|WgPallets|NoBoxes|WgBoxes|Cabinets|Racks|Batteries|Sited|Date_Enter' AS csv_output
UNION
SELECT
ID + '|'
+ LTL + '|'
+ Safely + '|'
+ Dock + '|'
+ Required + '|'
+ Hours + '|'
+ Dock + '|'
+ Jack + '|'
+ Dolly + '|'
+ convert(varchar(100), Pallets) + '|'
+ convert(varchar(100), wgPallets) + '|'
+ convert(varchar(100), NoBoxes) + '|'
+ convert(varchar(100), WgBoxes) + '|'
+ convert(varchar(100), Cabinets) + '|'
+ convert(varchar(100), Racks) + '|'
+ Batteries + '|'
+ Sited + '|'
+ convert(varchar(23),Date_Enter,121)
FROM
sales
;
Finally:
This is not very elegant. In the export options (which depend on the tool you use) there is normally an option to export the headers of the columns as a separate line and set the delimiter (in your case pipe symbol).
Personally I recommend this approach because I can use the same view for the results and be able to separate the logic for export and data selection from each other.

Using Union all to SQL Queries to create Dynamic Column Names

Please se my code below
set #query = 'SELECT tenantcode, locationd, name, MONTH,' +
'Year1 as' + '[' + #Year1 + ']' +
',Year2 as' + '[' + #Year2 + ']' +
',Year3 as' + '[' + #Year3 + ']' +
',Year4 as' + '[' + #Year4 + ']' +
',Year5 as' + '[' + #Year5 + ']' +
'from #SalesPerYear' +
'UNION ALL' +
'SELECT tenantcode, locationd, name, total , t1, t2,t3,t4,t5 FROM #TotalSales '
EXECUTE (#query)
That is part of my codes in the desire in achieving a final output in SQL WHERE COLUMN NAMES should be dynamic (in this case, the changing YEAR NAME such as 2011, 2012,2013 etc)
When execute my stored procedure, there is an error like this
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'tenantcode'.
When I remove the Union all, both queries worked individually. What could be the problem here.
You're missing a space between from #SalesPerYear and UNION ALL and also the following SELECT.
....
'from #SalesPerYear '
^---here
'UNION ALL' +
' SELECT tenantcode, locationd, name, total , t1, t2,t3,t4,t5 FROM #TotalSales '
^--- and here
Thats the easiest way to demonstrate it, you can of course just put a space either side of UNION ALL
' UNION ALL ' +

Strange behavior with ISNULL() in MSSQL

I have a select statement that is combining multiple segments of a persons name. This isn't anything new.
SELECT FirstName + ' ' + LastName AS FullName FROM MyTable
I then tried to add the middle initial to this and I came up with the following
SELECT FirstName + ' ' + ISNULL(MiddingInitial + ' ', '') + LastName AS FullName FROM MyTable
This appears to work, but during my testing of ISNULL(), I came across an odd behavior. I'm aware that NULL + 'any string' resolves to NULL. However this was just plain odd...
Here's my code, and what I get out as a result...
print '''' + isnull(null + 'Any String','Results in null') + ''''
print '''' + isnull(null + 'Any','Results in null') + ''''
print '''' + isnull(null + 'A','Results in null') + ''''
print '''' + isnull(null + '','Results in null') + ''''
/*
'Results in '
'Resu'
'Re'
'Re'
*/
Any idea of why this behavior occurs? Does it do the same for you?
It comes down to the datatypes you're working with and the behavior of the ISNULL function. Let's look at one example:
null + 'Any String'
The above fits perfectly into a varchar(11) datatype. The NULL (which is really just the result of char(0) and has length 1) and a regular 10-character string concatenated together makes for 11 characters total. The replacement string -- the second parameter to your ISNULL function -- is going to be forced to fit into a varchar(11), so it is truncated to 11 characters.
The pattern repeats for the remaining items, with a special case for the empty string.
If you don't want this to happen, use COALESCE, which instead of taking the datatype of the first item in the list, it uses data type precedence. A varchar(15) takes precedence over a varchar(11), so you will get the full replacement string:
print '''' + coalesce(null + 'Any String','Results in null') + ''''
print '''' + coalesce(null + 'Any','Results in null') + ''''
print '''' + coalesce(null + 'A','Results in null') + ''''
print '''' + coalesce(null + '','Results in null') + ''''
/*
'Results in null'
'Results in null'
'Results in null'
'Results in null'
*/

Single quote in a query

How can I insert an single quotes in a query ?
Example
select *, 'INSERT INTO San_Endereco (Endereco_Id, Logradouro_Id, Bairro_Id, CEP, Logradouro, Livre) VALUES
(' + CAST(Endereco_Id as varchar) + ','
+ CAST(Logradouro_Id as varchar) + ','
+ CAST(Bairro_Id as varchar) + ','
+ CAST (CEP as varchar) + ','
+ CAST(Logradouro as varchar) + ','
+ CAST(Livre as varchar) + ')' as teste
FROM San_Endereco
Before each CAST I need put the single quote. How can I do that ?
Use two single quotes: ''
select *, 'INSERT INTO San_Endereco (Endereco_Id, Logradouro_Id, Bairro_Id, CEP, Logradouro, Livre) VALUES
(''' + CAST(Endereco_Id as varchar) + ''','''
+ CAST(Logradouro_Id as varchar) + ''','''
+ CAST(Bairro_Id as varchar) + ''','''
+ CAST (CEP as varchar) + ''','''
+ CAST(Logradouro as varchar) + ''','''
+ CAST(Livre as varchar) + ''')''' as teste
FROM San_Endereco
Use double single quotes ''
If a single quote is contained in the actual data to be inserted, the command often becomes corrupted. To solve the problem, simply replace any single quote with two quotes (not the double quote character but two single-quote characters).
declare #var varchar(100)
select #var = 'txt'
select char(39)+#var+char(39) -- with single quote
select *, 'INSERT INTO San_Endereco (Endereco_Id, Logradouro_Id, Bairro_Id, CEP, Logradouro, Livre) VALUES
(''' + CAST(Endereco_Id as varchar) + ''','
+ ....
You have to use ' in string two times:
declare #var varchar(100)
select #var = 'txt'
select ' '+#var+' ' -- without single quote
select ''''+#var+'''' -- with single quote

Using System Tables to Count the Percent of Rows Null in Various Tables

I'm trying to determine the percent of null items for all fields of a table. I have to run this on several tables with a ton of fields, and I was looking for an automated way of doing this.
I know I can query "information_schema.columns" and get a nice clean list of field names ala:
select Column_name
from information_schema.columns
where table_name='TableName'
But I can't seem to come up with something quick and dirty to do the percentage count for each field, I'm guessing I'll need some dynamic sql of some sort? Anyone have a suggestion on a good way to approach this?
Maybe too simplistic, but the basic idea can be expanded in different ways (I normally have variables for #CRLF and #TAB for code generation):
DECLARE #sql AS varchar(MAX)
SELECT #sql = COALESCE(#sql + CHAR(13) + CHAR(10) + 'UNION' + CHAR(13) + CHAR(10), '')
+ 'SELECT ''' + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) + '.' + QUOTENAME(COLUMN_NAME) + ''' AS COLUMN_NAME' + CHAR(13) + CHAR(10)
+ CHAR(9) + ',COUNT(*) AS TotalRows' + CHAR(13) + CHAR(10)
+ CHAR(9) + ',COUNT(' + COLUMN_NAME + ') AS NonNullCount' + CHAR(13) + CHAR(10)
+ 'FROM ' + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS WHERE IS_NULLABLE = 'YES'
PRINT #sql
EXEC (#sql)
As far as your percentages, I wasn't sure if that was over the entire table or a particular column only, so I'll leave that as an exercise for the reader.
AFAIK the only way to do it is to use dynamic sql (e.g., sp_executesql). There are index statistics but nulls aren't stored in indexes...