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
Related
I'm trying to delete specific data from any tables in my SQL Server.
DB like this. I want to delete all Romios.
Dog.table
(NAME,AGE) = {(Romio,2), (Juliet,3)}
Cat.table
(NAME, Fur) = {(Romio,short), (Trump, bald)}
Cow.table
(Name, Mlik) = {(Romio, 10L), (Obama, 2L)}
Useless.table
(Use1, Use2) = {...}
So, I got tables list with the below code:
SELECT TABLE_NAME FROM information_schema.COLUMNS where COLUMN_NAME = 'NAME'
But, the next step doesn't work.
DELETE (SELECT TABLE_NAME FROM information_schema.COLUMNS where COLUMN_NAME = 'NAME') WHERE Name = 'Romio'
Yeah..... I know delete query only works for 1 table. That query has a problem.
How can I make it work?
Try this if you don't mind using dynamic TSQL, i.e. using EXEC
DECLARE #StrQuery nvarchar(MAX)
SELECT #StrQuery = ISNULL(#StrQuery, '') + 'DELETE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] WHERE NAME = ''Romio'' ' FROM information_schema.COLUMNS where COLUMN_NAME = 'NAME'
EXEC(#StrQuery)
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)
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.
what would be the simplest way to change every nvarchar column in a database to a varchar?
I personally would prefer nvarchar, but the data arch has specified that varchar must be used.
Here, to get you started:
Select 'Alter Table [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] Alter Column [' + COLUMN_NAME + '] VarChar(' + CAST(CHARACTER_MAXIMUM_LENGTH As VARCHAR) + ')'
From INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'NVARCHAR'
This will generate all the needed alter statements for you (cut, paste, run).
Note that this does not take any constraints into account.
In order to handle MAX and exclude the niggly sysdiagrams:
SELECT
'
ALTER TABLE [' + TABLE_SCHEMA + '].[' + TABLE_NAME + ']
ALTER COLUMN [' + COLUMN_NAME + ']
VARCHAR(' +
(CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1
THEN 'MAX'
ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR)
END)
+ ')
'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'NVARCHAR' AND TABLE_NAME <> 'SYSDIAGRAMS'
Ask the data arch to do it?
or
Generate a script of all objects in your system, alter then nvarchar's, then create a new database and import the data into it from the old one.
or
Write alter scripts to update the existing database.
(This may be the best approach if it's a production database, or a client database.)