Search for ampersand (&) when using containstable in MS SQL Server - sql

I'm using a stored procedure on a autocomplete dropdownlist to retreive a list of clients. Some of the clients have an '&' (ampersand) sign in the name e.g. 'H&M', 'Marks & Spencers' and users would like to search on the '&' sign.
When i directly use the & sign it uses it as a word breaker and does not pick the list which has '&' sign.
Is there any way i could search the table using the '&' and retreive values that have '&' sign.
Hope i've made sence explaining what i need to do.
Thanks for all your help!

Perhaps something like:
WHERE column LIKE REPLACE(#searchvalue, '&', '/&') ESCAPE '/'
Another idea:
DECLARE #randomstring #text
SET #randomstring ='randomstringthatwillneverbeusedforsearch'
WHERE REPLACE(column, #searchvalue, #randomstring) LIKE '%'+#randomstring+'%'
No idea about performance issues though.

Try this one -
DECLARE #char CHAR(1)
SELECT #char = '&'
DECLARE #sql NVARCHAR(MAX)
SELECT #sql = (
SELECT CHAR(13) +
'IF EXISTS(SELECT 1 FROM ' +
QUOTENAME(s.name) + '.' + QUOTENAME(o.name) +
' WHERE' + b.cols + ')
SELECT table_name = ''[' + s.name + '].[' + o.name + ']'' ' + c.cols +' FROM ' +
QUOTENAME(s.name) + '.' + QUOTENAME(o.name) +
' WHERE' + b.cols + ';'
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
JOIN (
SELECT DISTINCT p.[object_id]
FROM sys.partitions p
WHERE p.[rows] > 0
) p ON p.[object_id] = o.[object_id]
OUTER APPLY (
SELECT cols = STUFF((
SELECT 'OR CHARINDEX(''' + #char + ''', ' + QUOTENAME(c.name) + ') > 0 '
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE t.name IN ('char', 'nchar', 'ntext', 'nvarchar', 'text', 'varchar')
AND c.[object_id] = o.[object_id]
ORDER BY c.column_id
FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)'), 1, 2, '')
) b
OUTER APPLY (
SELECT cols = (
SELECT ', ' + QUOTENAME(c.name) + ' '
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE t.name IN ('char', 'nchar', 'ntext', 'nvarchar', 'text', 'varchar')
AND c.[object_id] = o.[object_id]
ORDER BY c.column_id
FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)')
) c
WHERE o.[type] = 'U'
AND b.cols IS NOT NULL
FOR XML PATH(''), TYPE, ROOT).value('root[1]', 'NVARCHAR(MAX)')
EXEC sys.sp_executesql #sql
This query searches for the substring in all db's which have tables with text fields -
DECLARE #phrase NVARCHAR(100)
SELECT #phrase = '&'
DECLARE
#db_name SYSNAME
, #output NVARCHAR(200)
DECLARE db CURSOR READ_ONLY FAST_FORWARD LOCAL FOR
SELECT d.name
FROM sys.databases d
WHERE d.state_desc = 'ONLINE'
AND d.name NOT IN ('tempdb', 'model', 'msdb', 'master')
--AND d.name = 'your db name'
ORDER BY d.name
OPEN db
FETCH NEXT FROM db INTO #db_name
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT #output = CONVERT(NVARCHAR(15), GETDATE(), 114) + ': Find in ' + QUOTENAME(#db_name) + ':'
RAISERROR(#output, 0, 1) WITH NOWAIT
DECLARE #tsql NVARCHAR(MAX) = '
USE [' + #db_name + '];
DECLARE #sql NVARCHAR(MAX)
SELECT #sql = ''USE [' + #db_name + '];'' + (
SELECT
CHAR(13) +
''IF EXISTS(SELECT 1 FROM '' +
QUOTENAME(s.name) + ''.'' + QUOTENAME(o.name) +
'' WHERE'' + b.cols + '') PRINT ''''['' +
s.name + ''].['' + o.name + '']'''';''
FROM sys.objects o
JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
JOIN (
SELECT DISTINCT p.[object_id]
FROM sys.partitions p
WHERE p.[rows] > 0
) p ON p.[object_id] = o.[object_id]
OUTER APPLY (
SELECT cols = STUFF((
SELECT ''OR CHARINDEX(''''' + #phrase + ''''', '' + QUOTENAME(c.name) + '') > 0 ''
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
WHERE t.name IN (''char'', ''nchar'', ''ntext'', ''nvarchar'', ''text'', ''varchar'')
AND c.[object_id] = o.[object_id]
ORDER BY c.column_id
FOR XML PATH(''''), TYPE, ROOT).value(''root[1]'', ''NVARCHAR(MAX)''), 1, 2, '''')
) b
WHERE o.[type] = ''U''
AND b.cols IS NOT NULL
FOR XML PATH(''''), TYPE, ROOT).value(''root[1]'', ''NVARCHAR(MAX)'')
EXEC sys.sp_executesql #sql
'
EXEC sys.sp_executesql #tsql
PRINT REPLICATE('-', 100) + CHAR(13)
FETCH NEXT FROM db INTO #db_name
END
CLOSE db
DEALLOCATE db

Related

A SELECT INTO statement cannot contain a SELECT statement that assigns values to a variable

I am trying to create a stored procedure or function to find the number of null values in each column in a table.
I am having problems determining the syntax for converting the code to a stored procedure/function.
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT '
' +
STUFF((
SELECT ', [' + c.name + '] = ' + CASE WHEN c.is_nullable = 0 THEN '0' ELSE 'COUNT(*) - COUNT([' + c.name + '])' END
FROM sys.columns c
WHERE c.[object_id] = o.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, 'SELECT ''' + SCHEMA_NAME(o.[schema_id]) + '.' + o.name + ''', COUNT(*), ') + '
FROM [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']'
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.is_ms_shipped = 0
AND [name] = 'BSEG'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
INTO xzy
PRINT #SQL
EXEC sys.sp_executesql #SQL
I want to stored the results in a table. But I am getting the following error message:
Msg 194, Level 15, State 1, Line 2
A SELECT INTO statement cannot contain a SELECT statement that assigns values to a variable.
So my ultimate aim is to have a stored procedure/function which upon execution will give number of null values in each column in a table and the results will be stored in another result table.
Can you please check with this following changes-
Remove assigning part from your query and just use the simple select statement as-
SELECT '' +
STUFF((
...
--Note: Write the SQL in such way so that only SQL
--text from STUFF functions is returned. There is no
--requirement of assigning the text first to variable #SQL
Add INSERT before INTO key as below-
...
INSERT INTO xzy
...
If still no luck, please provide output of PRINT #SQL command with above 2 changes.
The "INTO xyz" should go above "FROM sys.objects o"?
EDIT
Try this
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT '
' +
STUFF((
SELECT ', ' + CASE WHEN c.is_nullable = 0 THEN '0' ELSE 'COUNT(*) - COUNT([' + c.name + '])' END + ' AS [' + c.name + ']'
FROM sys.columns c
WHERE c.[object_id] = o.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, 'SELECT ''' + SCHEMA_NAME(o.[schema_id]) + '.' + o.name + ''' as TableName, COUNT(*) as Cnt, ') + '
INTO xzy
FROM [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']'
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.is_ms_shipped = 0
AND [name] = 'BSEG'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #SQL
EXEC sys.sp_executesql #SQL

SQL query optimization

I am trying to find out a script that can help me in Data Density of my DBs. the point is I already figure out the query and what I do need but the problem is the query takes for ever. it works find for small DBs, but that doesn't happen a lot.
So I am looking for kind of optimization or any ideas to help me.
the script:
DECLARE Cur CURSOR
FOR
SELECT DB_Name() AS DatabaseName
,s.[name] AS SchemaName
,t.[name] AS TableName
,c.[name] AS ColumnName
,'[' + DB_Name() + ']' + '.[' + s.NAME + '].' + '[' + T.NAME + ']' AS FullQualifiedTableName
,d.[name] AS DataType
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types d ON c.user_type_id = d.user_type_id
WHERE d.NAME LIKE '%int%'
OR d.NAME LIKE '%float%'
OR d.NAME LIKE '%decimal%'
OR d.NAME LIKE '%numeric%'
OR d.NAME LIKE '%real%'
OR d.NAME LIKE '%money%'
OR d.NAME LIKE '%date%'
OR d.NAME LIKE '%datetime%'
AND is_identity = 0
OPEN Cur
FETCH NEXT
FROM Cur
INTO #DatabaseName
,#SchemaName
,#TableName
,#ColumnName
,#FullyQualifiedTableName
,#DataType
WHILE ##FETCH_STATUS = 0 -- The FETCH statement was successful.
BEGIN
DECLARE #SQL VARCHAR(MAX) = NULL
SET #SQL = ' Select ''' + #DatabaseName + ''' AS DatabaseName, ''' +
#SchemaName + ''' AS TableName,
''' + #TableName + ''' AS SchemaName,
''' + #ColumnName + ''' AS ColumnName,
''' + #DataType + ''' AS ColumnName,
(Select MAX(' + #ColumnName + ') from ' + #FullyQualifiedTableName + ' with (nolock))
AS MaxValue,
(Select MIN(' + #ColumnName + ') from ' + #FullyQualifiedTableName + ' with (nolock))
AS MinValue,
(Select COUNT(*) from ' + #FullyQualifiedTableName + ' with (nolock))
AS CountValue,
(Select COUNT(*) from ' + #FullyQualifiedTableName + ' Where ' + #ColumnName + ' IS NOT NULL )
AS NotNULLCount,
(Select 0 from ' + #FullyQualifiedTableName + ')
AS DataDensity'
PRINT #SQL
The following script will give me the MAX, MIN, COUNT, NotNULLCount and the DATA DENSITY for every and each column form the declared types above. but u can imagine a DB with 70 tables and each table has 30-50 columns....
running this script will take for ever.
You should always try and avoid using cursors, this query will give you a list of select queries that you can copy and paste to get the data that you require. Note also I have removed the sub selects as they are not required:
SELECT 'Select ''' + DB_Name() + ''' AS DatabaseName, ''' + s.Name + ''' AS SchemaName, ''' + t.Name + ''' AS TableName, ''' + c.Name + ''' AS ColumnName, ''' + d.Name + ''' AS ColumnName,' +
'MAX([' + c.Name + ']) AS MaxValue,' +
'MIN([' + c.Name + ']) AS MinValue,' +
'COUNT(*) AS CountValue,' +
'COUNT([' + c.Name + ']) AS NotNullCount,' +
'CAST(COUNT(DISTINCT [' + c.name + ']) AS float) / COUNT([' + C.Name + ']) AS DataDensity ' +
'from [' + DB_Name() + '].[' + s.Name + '].[' + t.name + '] with (nolock)'
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types d ON c.user_type_id = d.user_type_id
WHERE d.NAME LIKE '%int%'
OR d.NAME LIKE '%float%'
OR d.NAME LIKE '%decimal%'
OR d.NAME LIKE '%numeric%'
OR d.NAME LIKE '%real%'
OR d.NAME LIKE '%money%'
OR d.NAME LIKE '%date%'
OR d.NAME LIKE '%datetime%'
AND is_identity = 0
This will give you a list of select statements in the following form:
Select 'MyDB' AS DatabaseName, 'dbo' AS SchemaName, 'MyTable' AS TableName, 'ID' AS ColumnName, 'int' AS ColumnName,MAX([ID]) AS MaxValue,MIN([ID]) AS MinValue,COUNT(*) AS CountValue,COUNT([ID]) AS NotNullCount,CAST(COUNT(DISTINCT [ID]) AS float) / COUNT([ID]) AS DataDensity from [MyDB].[dbo].[MyTable] with (nolock)
Of course SQL Server stores these sorts of statistics for useful columns, You can find which ones it has be using:
EXEC SP_HELPSTATS 'MyTable', 'ALL'
Then using the list of statistics returned such as:
_WA_Sys_00000014_004FB3FB ID
to get the actual stats using:
DBCC SHOW_STATISTICS('MyTable','_WA_Sys_00000002_004FB3FB')
This will return data like:
Name Updated Rows Rows Sampled Steps Density Average key length String Index Filter Expression Unfiltered Rows
_WA_Sys_00000002_004FB3FB Jan 8 2017 8:01PM 16535 16535 200 0.2493151 4.459389 NO NULL 16535
and
All density Average Length Columns
0.0006038647 4.459389 EffectiveDate
and another rowset showing a histogram of values.
You can automatically generate these DBCC commands using:
SELECT 'DBCC SHOW_STATISTICS([' + OBJECT_NAME(s.object_Id) + '],''' + s.Name + ''')'
FROM sys.stats s
INNER JOIN sys.stats_columns sc
ON s.object_id = sc.object_id AND s.stats_id = sc.stats_id
INNER JOIN sys.columns c
ON sc.object_id = c.object_id AND sc.column_id = c.column_id
WHERE s.Name LIKE '_WA%'
ORDER BY s.stats_id, sc.column_id;

SQL get table columns with type name

I have successfully getting the information of tables and columns from below query.
Is there any handy way to get the type name with the description like nvarchar(20), numeric(14,2), varchar(max) etc. instead of lot's of CASE statements?
SELECT
o.name AS TableName,
c.name AS ColumnName,
t.name +
CASE
WHEN t.name LIKE '%char' THEN '(' +
CASE
WHEN c.max_length = -1 THEN 'max'
ELSE CONVERT(varchar(10), c.max_length / CASE WHEN t.name LIKE 'n%' THEN 2 ELSE 1 END)
END + ')'
WHEN t.name IN ('numeric', 'decimal') THEN '(' + CONVERT(varchar(4), c.precision) + ',' + CONVERT(varchar(4), c.scale) + ')'
-- WHEN .... many other types
ELSE ''
END AS TypeName
FROM
sys.objects o
INNER JOIN sys.columns c ON o.object_id = c.object_id
INNER JOIN sys.types t ON t.system_type_id = c.system_type_id AND t.user_type_id = c.user_type_id
WHERE
o.is_ms_shipped = 0
ORDER BY
o.name,
c.column_id
Edit
sp_help nor the information schema return the name not being like nvarchar(20), numeric(14,2), varchar(max)
I use this view to Document the Database.... you could used this and use the data_type and Length/Precision
/****** Object: View [dbo].[vw_DataDictionary] Script Date: 17/07/2015 10:24:04 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER VIEW [dbo].[vw_DataDictionary]
AS
SELECT TOP (100) PERCENT tb.name AS Table_Name, CAST(ept.value AS nvarchar(200)) AS Table_Description, CAST(c.name AS nvarchar(200)) AS Column_Name,
CAST(ep.value AS nvarchar(200)) AS column_Description, t.name AS data_type, c.is_nullable AS Is_Null, object_definition(c.default_object_id) AS default_text,
c.max_length AS Length, c.precision AS numeric_precision, c.scale AS numeric_scale, c.column_id
FROM sys.columns AS c LEFT OUTER JOIN
sys.tables AS tb ON tb.object_id = c.object_id LEFT OUTER JOIN
sys.types AS t ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id LEFT OUTER JOIN
sys.extended_properties AS ept ON ept.major_id = tb.object_id AND ept.minor_id = 0 AND ept.name = 'MS_Description' LEFT OUTER JOIN
sys.extended_properties AS ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.name = 'MS_Description'
WHERE (tb.type = 'U') AND (tb.name <> 'sysdiagrams')
ORDER BY Table_Name, c.column_id
GO
For SQL Server 2008 R2, I have declared the type by CASE as below:
SQL Fiddle
SELECT
DB_NAME() AS DatabaseName,
SCHEMA_NAME(o.schema_id) AS SchemaName,
o.name AS ObjectName,
c.name AS ColumnName,
RTRIM(o.type) AS ObjectType,
t.name AS TypeName,
c.max_length AS Length,
-- The logic is implemented in this column
t.name +
CASE
-- (max) for char type / binary only
WHEN (t.name LIKE '%char%' OR t.name LIKE '%binary') AND c.max_length = -1 THEN '(max)'
-- (n) where n = length / 2 for nchar and nvarchar
WHEN t.name LIKE '%char%' AND LEFT(t.name, 1) = 'n' THEN '(' + CONVERT(varchar, c.max_length / 2) + ')'
-- (n) where n = length
WHEN t.name LIKE '%char%' OR t.name LIKE '%binary' THEN '(' + CONVERT(varchar, c.max_length) + ')'
-- (p,s) where p = precision, s = scale
WHEN t.name IN ('numeric', 'decimal') THEN '(' + CONVERT(varchar, c.precision) + ',' + CONVERT(varchar, c.scale) + ')'
-- (s) where s = scale
WHEN t.name IN ('time', 'datetime2', 'datetimeoffset') THEN '(' + CONVERT(varchar, c.scale) + ')'
ELSE ''
END AS Type
FROM
sys.objects o
inner join sys.columns c on o.object_id = c.object_id
inner join sys.types t on c.system_type_id = t.system_type_id and c.user_type_id = t.user_type_id
WHERE 1 = 1
AND o.is_ms_shipped = 1
This should help you, Adopted from here
DECLARE #tblname VARCHAR(300)
SET #tblname = 'tblname'
SELECT o.list AS ColumnsDescription
FROM sysobjects so
CROSS APPLY (
SELECT ' [' + column_name + '] ' + data_type + CASE data_type
WHEN 'sql_variant'
THEN ''
WHEN 'text'
THEN ''
WHEN 'ntext'
THEN ''
WHEN 'xml'
THEN ''
WHEN 'decimal'
THEN '(' + cast(numeric_precision AS VARCHAR) + ', ' + cast(numeric_scale AS VARCHAR) + ')'
ELSE coalesce('(' + CASE
WHEN character_maximum_length = - 1
THEN 'MAX'
ELSE cast(character_maximum_length AS VARCHAR)
END + ')', '')
END + ' ' + CASE
WHEN EXISTS (
SELECT id
FROM syscolumns
WHERE object_name(id) = so.NAME
AND NAME = column_name
AND columnproperty(id, NAME, 'IsIdentity') = 1
)
THEN 'IDENTITY(' + cast(ident_seed(so.NAME) AS VARCHAR) + ',' + cast(ident_incr(so.NAME) AS VARCHAR) + ')'
ELSE ''
END + ' ' + (
CASE
WHEN IS_NULLABLE = 'No'
THEN 'NOT '
ELSE ''
END
) + 'NULL ' + CASE
WHEN information_schema.columns.COLUMN_DEFAULT IS NOT NULL
THEN 'DEFAULT ' + information_schema.columns.COLUMN_DEFAULT
ELSE ''
END + ', '
FROM information_schema.columns
WHERE table_name = so.NAME
ORDER BY ordinal_position
FOR XML PATH('')
) o(list)
LEFT JOIN information_schema.table_constraints tc ON tc.Table_name = so.NAME
AND tc.Constraint_Type = 'PRIMARY KEY'
CROSS APPLY (
SELECT '[' + Column_Name + '], '
FROM information_schema.key_column_usage kcu
WHERE kcu.Constraint_Name = tc.Constraint_Name
ORDER BY ORDINAL_POSITION
FOR XML PATH('')
) j(list)
WHERE xtype = 'U'
AND NAME = #tblname
You can parse your results as you want.
SELECT
COLUMN_NAME,
CASE
WHEN DATA_TYPE ='decimal' THEN DATA_TYPE+ '('+cast (NUMERIC_PRECISION as Varchar)+ ','+cast (NUMERIC_SCALE as Varchar)+ ')'
WHEN CHARACTER_MAXIMUM_LENGTH is null THEN DATA_TYPE + cast ('' as Varchar)
ELSE DATA_TYPE + '('+ cast (CHARACTER_MAXIMUM_LENGTH as Varchar)+')' END AS QuantityText
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'table_name' and TABLE_SCHEMA = 'dbo'
order by COLUMN_NAME

find all columns and tables in a database which contain a particular case sensitive string

I would like to find all the tables in my database where the columns "Column1" & "Column2" contain a specific case sensitive string 'aBcD'.Is there a way to do it ?
I came up with the following query . Any suggestions ?
SELECT c.name AS ColName, t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'Column1' or c.name = 'Column2' and
/* column contents is 'aBcD' */ ?
One solution could be to iterate over all found tables and check their content like this:
DECLARE cur CURSOR FOR
SELECT t.name, c.name
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name = 'Column1' or c.name = 'Column2'
OPEN cur
CREATE TABLE #output(tablename nvarchar(255), columnname nvarchar(255))
DECLARE #sql nvarchar(max), #tab nvarchar(max), #col nvarchar(max)
FETCH NEXT FROM cur INTO #tab, #col
WHILE(##FETCH_STATUS = 0) BEGIN
SET #sql = N'
IF(SELECT COUNT(*)
FROM '+#tab+'
WHERE '+#col+' = N''aBcD''
COLLATE Latin1_General_CS_AS) > 0
INSERT INTO #output(tablename, columname)
VALUES(N'''+#tab+''',N'''+#col+''')'
EXEC(#sql)
FETCH NEXT FROM cur INTO #tab, #col
END
SELECT * FROM #output
-- Cleanup
CLOSE cur
DEALLOCATE cur
DROP TABLE #output
My buddy Chris Morris at sqlservercentral.com posted this a few years ago. I modified it slightly to be a little more flexible. This will generate a series of select statements which is much faster than using a cursor. If you wanted to you could shove the results of this into a variable and execute it. Or you can just copy and paste several of these into another query window and run them.
DECLARE #MySearchCriteria VARCHAR(500)
SET #MySearchCriteria = '''This user registration has been rejected''' --you do need all these quotation marks because this string is injected to another string.
SELECT 'SELECT ' + c.columnlist + '] FROM [' + t.name + '] WHERE ' + w.whereclause + ';' as SelectStatement
FROM sys.tables t
CROSS APPLY (
SELECT STUFF((
SELECT '], [' + c.Name AS [text()]
FROM sys.columns c
join sys.types t2 on t2.user_type_id = c.user_type_id
WHERE t.object_id = c.object_id
AND c.collation_name IS NOT NULL
AND c.max_length > 6
and t2.name not in ('text', 'ntext')
FOR XML PATH('')
), 1, 2, '' )
) c (columnlist)
CROSS APPLY (
SELECT STUFF((
SELECT ' OR [' + c.Name + '] IN (' + #MySearchCriteria + ')' AS [text()]
FROM sys.columns c
join sys.types t2 on t2.user_type_id = c.user_type_id
WHERE t.object_id = c.object_id
AND c.collation_name IS NOT NULL
AND c.max_length > 6
and t2.name not in ('text', 'ntext')
FOR XML PATH('')
), 1, 4, '' )
) w (whereclause)
where c.columnlist is not null
ORDER BY t.name

SQL Unpivot With Every Column

I have the below query which works well for the 4 columns chosen, but the issue is that I need to select every column of the table (there is about 50 columns). Is there an easier way to do this instead without including each of the 50 columns in the SELECT and IN statements. I also realize that there could be a data type issue. There is only 1 row of data returned.
SELECT g.property,
g.value
FROM (SELECT applicationversion,
ftpservername,
smtpservername,
Cast(numberofservers AS NVARCHAR(max)) AS numberofservers
FROM globals) Person
UNPIVOT (value
FOR property IN (applicationversion,
ftpservername,
smtpservername,
numberofservers)) AS g;
Please try this:
DECLARE #sql AS NVARCHAR(MAX)
DECLARE #cols1 AS NVARCHAR(MAX)
DECLARE #cols2 AS NVARCHAR(MAX)
SELECT #cols1= ISNULL(#cols1 + ',','') + QUOTENAME(name)
FROM (select c.name from sys.tables t
inner join sys.columns c on c.object_id = t.object_id
where t.name = 'globals'
) cols1
SELECT #cols2= ISNULL(#cols2 + ',cast(','cast(') + QUOTENAME(name) + ' as nvarchar(max))'+ QUOTENAME(name)
FROM (select c.name from sys.tables t
inner join sys.columns c on c.object_id = t.object_id
where t.name = 'globals'
) cols2
SET #sql =
N'SELECT g.property, g.value
FROM (SELECT ' + #cols2 + '
FROM globals) Person
UNPIVOT (value
FOR property IN (' + #cols1 +')) AS g; '
EXEC sp_executesql #sql
It's not beautiful and can certainly be improved, but it should work.
Slight improvement to jpw's version
DECLARE #sql AS NVARCHAR(MAX)
DECLARE #cols1 AS NVARCHAR(MAX)
DECLARE #cols2 AS NVARCHAR(MAX)
SELECT #cols1= ISNULL(#cols1 + ',','') + QUOTENAME(name), #cols2= ISNULL(#cols2 + ',cast(','cast(') + QUOTENAME(name) + ' as nvarchar(max))'+ QUOTENAME(name)
FROM (select c.name from sys.tables t
inner join sys.columns c on c.object_id = t.object_id
where t.name = 'globals'
) cols1
SET #sql =
N'SELECT g.property, g.value
FROM (SELECT ' + #cols2 + '
FROM globals) Person
UNPIVOT (value
FOR property IN (' + #cols1 +')) AS g; '
EXEC sp_executesql #sql