How can I check if any column in a given table only have null or empty string values? Can I in some way extend this for every table in the database?
Here is a stored proc for finding an arbitrary value in the database. It's a fairly small modification to make it search for empty columns.
The procedure generates a list of all the tables and all the columns in the database, and creates a temporary table for storing the results. Then it generates a dynamic SQL and uses the INSERT INTO ... EXEC to fill the result table.
Here's a runnable example off the StackOverflow database:
-- Look for NULLs
DECLARE #sql AS varchar(max)
SELECT #sql = COALESCE(#sql + ' UNION ALL ', '') + sql
FROM (
SELECT 'SELECT ''' + c.TABLE_NAME + '.' + c.COLUMN_NAME + ''' AS COLUMN_NAME, COUNT(NULLIF(' + QUOTENAME(c.COLUMN_NAME) + ', '''')) AS NON_NULL_COUNT, COUNT(*) AS TOTAL_COUNT FROM ' + QUOTENAME(c.TABLE_CATALOG) + '.' + QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME) AS sql
FROM INFORMATION_SCHEMA.COLUMNS AS c
INNER JOIN INFORMATION_SCHEMA.TABLES AS t
ON t.TABLE_CATALOG = c.TABLE_CATALOG
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
WHERE c.DATA_TYPE IN ('nvarchar', 'varchar')
UNION ALL
SELECT 'SELECT ''' + c.TABLE_NAME + '.' + c.COLUMN_NAME + ''' AS COLUMN_NAME, COUNT(' + QUOTENAME(c.COLUMN_NAME) + ') AS NON_NULL_COUNT, COUNT(*) AS TOTAL_COUNT FROM ' + QUOTENAME(c.TABLE_CATALOG) + '.' + QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME) AS sql
FROM INFORMATION_SCHEMA.COLUMNS AS c
INNER JOIN INFORMATION_SCHEMA.TABLES AS t
ON t.TABLE_CATALOG = c.TABLE_CATALOG
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
WHERE c.DATA_TYPE NOT IN ('nvarchar', 'varchar')
AND c.IS_NULLABLE = 'YES'
) AS checks
SET #sql = 'SELECT * FROM (' + #sql + ') AS checks WHERE NON_NULL_COUNT = 0'
EXEC (#sql)
A few things to note:
There are two columns it finds which are completely NULL/blank:
Posts.OwnerDisplayName, Bdges.CreationDate
It converts '' to NULL for nvarchar and varchar columns (if you have char or nchar columns, you would have to change this)
You can't normally put a condition on a query for all columns in a table. You have to pick the columns you want. To get around this you need dynamic sql and the information_schema views.
Related
I am rather new to this and I am having a hard time into converting the below SQL query into an UPDATE statement for a stored procedure.
SELECT 'select'+
stuff((
SELECT ',' + 'dbo.' + Function_Name + '(' + Parameters_List + ')' FROM
[SPECIFIC_DATABASE]..Specific_table c WHERE c.Table_Name = t.Table_Name FOR
XML PATH('')),1,1,'')
+' from [' + Database_Name +'].[dbo].['+Table_Name+'] '
+ 'Where Audit_ID>' + CAST(#Audit_ID as nvarchar(100))
As 'Specific Queries'
FROM (SELECT Distinct Database_Name, Table_Name FROM [SPECIFIC_DATABASE]..Specific_table) t
The UPDATE query should be something like
UPDATE Table_name
SET Column_name = Function_Name(Parameters_List)
WHERE Audit_id >= #Audit_ID
FROM [SPECIFIC_DATABASE]..Specific_table
Any suggestions and guidelines on this would be much appreciated!
I think this should give you what you want, but I don't see any any reference to a Column_Name, so I'm assuming you will hardcode that.
select 'UPDATE tbl' + stuff((
select ' set Column_Name = ' + 'dbo.' + Function_Name + '(' + Parameters_List + ')'
from [SPECIFIC_DATABASE]..Specific_table c
where c.Table_Name = t.Table_Name
for xml PATH('')
), 1, 1, '')
+ ' from [' + Database_Name + '].[dbo].[' + Table_Name + '] tbl'
+ 'Where Audit_ID>'
+ CAST(#Audit_ID as nvarchar(100)) as 'Specific Queries'
from (
select distinct Database_Name, Table_Name
from [SPECIFIC_DATABASE]..Specific_table
) t
If the answer's not right then it might be helpful if you post what is the current output of your first query and maybe some more details as to what are the contents of the table called "Specific_table".
I've been trying to come up with a query that will list the name of every column in a table with it's max length.
This is in SQL Server 2012.
Any help is greatly appreciated.
You can use below query to get the the Actual and used length of the columns in a table
DECLARE #TSQL VARCHAR(MAX) = ''
DECLARE #TableName sysname = 't1'
SELECT #TSQL = #TSQL + 'SELECT ' + QUOTENAME(sc.name, '''') + ' AS ColumnName, ' + QUOTENAME(t.name, '''') + ' AS DataType, ' +
QUOTENAME(sc.max_length, '''') + ' AS ActualLength, MAX(DATALENGTH(' + QUOTENAME(sc.name) + ')) AS UsedLength FROM '+#TableName+ char(10) +' UNION '
FROM sys.columns sc
JOIN sys.types t on t.system_type_id = sc.system_type_id and t.name != 'sysname'
WHERE sc.OBJECT_ID = OBJECT_ID(#TableName)
SET #TSQL = LEFT(#TSQL, LEN(#TSQL)-6)
EXEC(#TSQL)
If you want know your table detail use information_schema.columns
select *
from information_schema.columns
where table_name = 'YourTableName'
If you want the lenght of a string field use LEN
select len(field1)
from YourTableName
I have a SQL table with about 50 columns. I want to be able to iterate through each one similar to a foreach loop. When I iterate through each column, I want to check to see if there's a single double quote appended at the end, and if so, remove it.
I have this solution built out but I explicitly define the column names, see below:
select BrandName =
(CASE
WHEN (BrandName like '%"') THEN LEFT(BrandName, LEN(BrandName) - 1)
ELSE BrandName
END),
emailSubject =
(CASE
WHEN (emailSubject like '%"') THEN LEFT(emailSubject , LEN(emailSubject ) - 1)
ELSE emailSubject
END),
-- and so on...
from tableName
This works fine, but introduces some possibility of error. So, this is why I want to do something like (pseudocode):
foreach column c in table
if (c.EndsWith('"'))
c.RemoveEndCharacter()
Is this possible, and if so can you provide some examples on how I might implement such a solution in T-SQL?
Thanks!
You can generate tsql statements to update your table with the code below. Execute the statement, then copy/paste the output into a new query window and run. Alternatively, you could use the query below for a cursor and execute the output on each iteration.
SELECT 'UPDATE [' + c.TABLE_SCHEMA + '].[' + c.TABLE_NAME + '] SET [' + c.COLUMN_NAME + '] = LEFT([' + c.COLUMN_NAME + '], LEN([' + c.COLUMN_NAME + ']) - 1) WHERE [' + c.COLUMN_NAME + '] LIKE ''%"'''
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN INFORMATION_SCHEMA.TABLES t
ON t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
--For simple demo purposes, assume tables only.
WHERE t.TABLE_TYPE = 'BASE TABLE'
--Did I miss any data types?
AND c.DATA_TYPE IN ('NVARCHAR', 'VARCHAR', 'NCHAR', 'CHAR')
--Replace values with your corresponding schema/table name.
AND c.TABLE_SCHEMA = 'dbo'
AND c.TABLE_NAME = 'YourTableName'
ORDER BY c.TABLE_SCHEMA, c.TABLE_NAME, c.ORDINAL_POSITION
So what I want is to have a table of distinct values and the count for those values. basically I want it to look like this:
DistinctValue | Count
Bob | 4
Fred | 5
George | 2
Joeseph | 1
for a single table I use :
SELECT ColumnName, COUNT(*) from TableName group by Column
How would I do this so that it would span across multiple tables. I have about say 30, possibly more, tables I need to do this for.
Any help would be greatly appreciated. Let me know if there's more information you need. Oh, and there's no worry about the column name because all the tables have the same column name.
WITH mytbl AS (
SELECT ColumnName, COUNT(*) AS myCount from TableName group by Column
UNION ALL
SELECT ColumnName, COUNT(*) from TableName2 group by Column
... a union all for every table
)
SELECT ColumnName, SUM(myCount)
FROM mytbl
GROUP BY ColumnName
-- If you are using an earlier version of MS SQL, the UNION statements can be put in a big sub select or a table variable.
-- IE, they'd take the place of mytbl in the last query replace mytbl in the bottom query with the UNIONS from the CTE
SELECT
t.name,
count(c.name) as columnsname
FROM
sys.tables t
inner join sys.columns c
ON t.object_id = c.object_id
group by t.name
You'll need to create and execute dynamic tsql to get your results:
DECLARE #Tsql NVARCHAR(MAX) = ''
DECLARE #ColumnName SYSNAME = 'YourColumnName'
SELECT #Tsql = #Tsql + 'SELECT ''[' + c.TABLE_SCHEMA + '].[' + c.TABLE_NAME + ']'' AS TableName, ' +
'[' + #ColumnName + '], COUNT(*) AS RecordCount FROM [' + c.TABLE_SCHEMA + '].[' + c.TABLE_NAME + '] GROUP BY [' + #ColumnName + '] UNION ' + CHAR(13) + CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN INFORMATION_SCHEMA.TABLES t
ON t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
--Comment out the next line if you want data/counts for views too.
AND t.TABLE_TYPE = 'BASE TABLE'
WHERE c.COLUMN_NAME = #ColumnName
--Remove the last UNION (and carriage-return, line-feed)
SELECT #Tsql = LEFT(#Tsql, LEN(#Tsql) - 8)
--Verify query.
PRINT #Tsql
--Uncomment when ready to proceed.
--EXEC (#Tsql)
Can someone assist me with listing all SQL "views" with the column names?
I've tried using the query below but I also need the columns for views only.
select * from information_schema.view_column_usage
What format do you want the results in? The following query will list all the views on the system and the columns they reference.
SELECT
'[' + VIEW_SCHEMA + '].[' + VIEW_NAME + ']' as [View]
,'[' + TABLE_SCHEMA + '].[' + TABLE_NAME + '].[' + COLUMN_NAME + ']' as [Column]
FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE
ORDER BY 1
View can be treated as normal tables in this example. Try this:
SELECT t.TABLE_SCHEMA, t.TABLE_NAME, c.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLES t
JOIN INFORMATION_SCHEMA.COLUMNS c
ON t.TABLE_NAME = c.TABLE_NAME
WHERE t.TABLE_NAME IN (
SELECT table_name FROM INFORMATION_SCHEMA.VIEWS)