How to search for specific column name within one table - sql

I have searched this question on stackoverflow but most of the questions are a little deeper than what I want. Many questions are relating to finding the table that has the specific column name.
I am connected to the database through SSMS. I have found the table that I want to search through by SELECT * FROM Item. In the Item table I want to search all of the field names (or name of the column) and select the ones that contain a specific string 'Size'. I thought something like this would work
Select * FROM Item WHERE column_name LIKE '%SIZE%'
It doesn't work though. How do I specify it to search through all of the column names to find the names that contain 'Size'?
Thanks.

This should be the generic query to get you to what you want.
USE [database_name]
GO
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%SIZE%'
AND t.name = 'Item'
ORDER BY schema_name, table_name;
You will need the correct permission on whichever SQL login that you run this through.

SELECT [Name]
FROM sys.columns
WHERE OBJECT_NAME(object_id)='Item'
AND [Name] LIKE '%Size%';

You can use
SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME ='zzzzz' and COLUMN_NAME like '%size%'

This looks through table named Item for a Column with the name like 'SIZE':
SELECT sch.COLUMN_NAME, sch.*
FROM INFORMATION_SCHEMA.COLUMNS AS sch
WHERE TABLE_NAME = 'Item'
AND COLUMN_NAME LIKE '%SIZE%'
Is this what you wanted?

I think this is what you are looking for, just replace database_Name with your db name:
Declare #myQuery varchar(max) = ' Select ';
Declare #columnName varchar(max) = '';
Declare GetColumnNames Cursor
For
SELECT COLUMN_NAME
FROM database_Name.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'Item'
And database_Name.INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME like '%SIZE%'
OPEN GetColumnNames
FETCH NEXT FROM GetColumnNames
INTO #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
Set #myQuery += #columnName + ', '
FETCH NEXT FROM GetColumnNames
INTO #columnName
END
CLOSE GetColumnNames;
DEALLOCATE GetColumnNames;
-- Chop off the end character
SET #myQuery = LEFT(#myQuery, LEN(#myQuery) - 1)
Set #myQuery += ' From Item'
exec(#myQuery)

You'll have to take a two step approach to achieve your end query.
First, you'll need to identify the columns you're interested in by using the table metadata, which you can get from either the sys schema or the INFORMATION_SCHEMA tables. Several of the proposed answers will help you get that information.
Next, you'll use the column names you've identified in step one to build the actual query you're interested in. If this is a one-off task you're doing, just copy and paste the results from the meta data query into a new SELECT query as your column list. If you need to do this task programmatically or multiple times using different LIKE strings, then you'll want to invest the time in writing some dynamic SQL.
When you wrap it all up, it'll look something like this:
--Step 1; The meta data part
DECLARE #ColumnList NVARCHAR(MAX)
,#SQL NVARCHAR(MAX)
SELECT
#ColumnList = COALESCE(#ColumnList+',','') + COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'schema'
AND
TABLE_NAME = 'TableName'
AND
COLUMN_NAME LIKE '%SIZE%'
SELECT #ColumnList;
--Step 2; The dynamic SQL part
SET #SQL = 'SELECT ' + #ColumnList + ' FROM schema.TableName;';
EXECUTE sys.sp_executesql #SQL;

Related

SQL Server 2008: create trigger across all tables in db

Using SQL Server 2008, I've created a database where every table has a datetime column called "CreatedDt". What I'd like to do is create a trigger for each table so that when a value is inserted, the CreatedDt column is populated with the current date and time.
If you'll pardon my pseudocode, what I'm after is the T-SQL equivalent of:
foreach (Table in MyDatabase)
{
create trigger CreatedDtTrigger
{
on insert createddt = datetime.now;
}
}
If anyone would care to help out, I'd greatly appreciate it. Thanks!
As #EricZ says, the best thing to do is bind a default for the column. Here's how you'd add it to every table using a cursor and dynamic SQL:
Sure, You can do it with a cursor:
declare #table sysname, #cmd nvarchar(max)
declare c cursor for
select name from sys.tables where is_ms_shipped = 0 order by name
open c; fetch next from c into #table
while ##fetch_status = 0
begin
set #cmd = 'ALTER TABLE ' + #table + ' ADD CONSTRAINT DF_' + #table + '_CreateDt DEFAULT GETDATE() FOR CreateDt'
exec sp_executesql #cmd
fetch next from c into #table
end
close c; deallocate c
No need to go for Cursors. Just copy the result of below Query and Execute.
select distinct 'ALTER TABLE '+ t.name +
' ADD CONSTRAINT DF_'+t.name+'_crdt DEFAULT getdate() FOR '+ c.name
from sys.tables t
inner join sys.columns c on t.object_id=c.object_id
where c.name like '%your column name%'
Here's another method:
DECLARE #SQL nvarchar(max);
SELECT #SQL = Coalesce(#SQL + '
', '')
+ 'ALTER TABLE ' + QuoteName(T.TABLE_SCHEMA) + '.' + QuoteName(T.TABLE_NAME)
+ ' ADD CONSTRAINT ' + QuoteName('DF_'
+ CASE WHEN T.TABLE_SCHEMA <> 'dbo' THEN T.Table_Schema + '_' ELSE '' END
+ C.COLUMN_NAME) + ' DEFAULT (GetDate()) FOR ' + QuoteName(C.COLUMN_NAME)
+ ';'
FROM
INFORMATION_SCHEMA.TABLES T
INNER JOIN INFORMATION_SCHEMA.COLUMNS C
ON T.TABLE_SCHEMA = C.TABLE_SCHEMA
AND T.TABLE_NAME = C.TABLE_NAME
WHERE
C.COLUMN_NAME = 'CreatedDt'
;
EXEC (#SQL);
This yields, and runs, a series of statements similar to the following:
ALTER TABLE [schema].[TableName] -- (line break added)
ADD CONSTRAINT [DF_schema_TableName] DEFAULT (GetDate()) FOR [ColumnName];
Some notes:
This uses the INFORMATION_SCHEMA views. It is best practice to use these where possible instead of the system tables because they are guaranteed to not change between versions of SQL Server (and moreover are supported on many DBMSes, so all things being equal it's best to use standards-compliant/portable code).
In a database with a case-sensitive default collation, one MUST use upper case for the INFORMATION_SCHEMA view names and column names.
When creating script it's important to pay attention to schema names and proper escaping (using QuoteName). Not doing so will break in someone's system some day.
I think it is best practice to put the DEFAULT expression inside parentheses. While no error is received without it in this case, with it, if the function GetDate() is parameterized and/or ever changed to a more complex expression, nothing will break.
If you decide that column defaults are not going to work for you, then the triggers you imagined are still possible. But it will take some serious work to manage whether the trigger already exists and alter or create it appropriately, JOIN to the inserted meta-table inside the trigger, and do it based on the full list of primary key columns for the table (if they exist, and if they don't, then you're out of luck). It is quite possible, but extremely difficult--you could end up with nested, nested, nested dynamic SQL. I have such automated object-creating script that contains 13 quote marks in a row...

TSQL Update stmt for each column name according to data type

For SSIS, I need to create a TSQL update workflow to overwrite the current table records in case of an import error.
I already have a set up for the whole SSIS process but I'm missing the SQL update statement.
So if something goes wrong during the import the current records (all rows) in the table should be updated with a short message - "Error DB Import" for example.
Since I have multiple tables to deal with I also get different column names and data types.
I would use this stmt to get the column names
SELECT COLUMN_NAME , *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable'
but how can I set a string message for the char types and NULL for numeric and date types. Using a CASE stmt?
In pseudo-code it's probably just a loop through the columns: if column_name is of data_type "char" then...
I also need to ignore the first 4 columns of each table so that I don't overwrite ID, Date, etc.
If you can help me set up a static test update stmt I'm sure I will be able to transfer this to my SSIS project.
Thank you.
Sounds like you're looking for something like this:
SELECT
CASE DATA_TYPE
WHEN 'int' THEN NULL
WHEN 'varchar' THEN 'STRING MSG GOES HERE'
END,
COLUMN_NAME , *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable'
AND ORDINAL_POSITION > 4
SQL Fiddle Demo
You can add as many WHEN clauses to the CASE statement as needed. Also, you want to use the ORDINAL_POSITION column to exclude the first 4 columns.
If you need to use this information to create an UPDATE statement, then you'll need to do that with Dynamic SQL.
EDIT -- Dynamic SQL:
create procedure updateMyTable
as
begin
declare #sql varchar(max)
SELECT #sql = 'UPDATE myTable SET ' +
STUFF(
(SELECT ', ' + COLUMN_NAME + ' = ' +
CASE DATA_TYPE
WHEN 'int' THEN 'NULL'
WHEN 'varchar' THEN '''STRING MSG GOES HERE'''
END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable'
for xml path(''))
,1,1,'')
exec(#sql)
end
SQL Fiddle Demo

query columns from many tables using dynamic SQL or Correlated Subquery on SQL Server INFORMATION_SCHEMA

I want to list all the Manufacturers identified in an SQL Server database.
There are many tables with manufacturer names in them, but they are not always in a nicely named column. However, column names are LIKE %manuf%.
So:
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%manuf%'
ORDER BY TABLE_NAME;
gets me a list of tables I want to query from and the column name I want to query.
How can I now query the manufacturer names from those tables?
If you want all of them returned in one result set you can use this query:
DECLARE #cmd NVARCHAR(MAX);
SET #cmd = STUFF((
SELECT ' UNION ALL SELECT '+QUOTENAME(COLUMN_NAME)+' FROM '+QUOTENAME(TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%manuf%'
ORDER BY TABLE_NAME
FOR XML PATH(''),TYPE
).value('.','NVARCHAR(MAX)'),1,11,'')
;
EXEC( #cmd);
That requires all of them to be a (n)varchar data type. If you run into problems add a cast:
SELECT ' UNION ALL SELECT CAST('+QUOTENAME(COLUMN_NAME)+' AS NVARCHAR(MAX)) FROM '+QUOTENAME(TABLE_NAME)
This seems like a very odd database design. You might want to revisit that...
If INFORMATION_SCHEMA isn't working for you use this:
DECLARE #cmd NVARCHAR(MAX);
SET #cmd = STUFF((
SELECT ' UNION ALL SELECT '+QUOTENAME(c.name)+' FROM dbo.'+QUOTENAME(t.name)
FROM sys.columns c
JOIN sys.tables t
ON c.object_id = t.object_id
WHERE c.name LIKE '%name%'
AND t.is_ms_shipped = 0
ORDER BY t.name
FOR XML PATH(''),TYPE
).value('.','NVARCHAR(MAX)'),1,11,'')
;
EXEC( #cmd);
While INFORMATION_SCHEMA is part of the ANSI standard, using the SQL Server catalog views is usually the preferred way to go anyway.
One more thing: If INFORMATION_SCHEMA returns incorrect results, you might have some kind of corruption going on, you should check that by running DBCC CHECKDB in that database.

Search of table names

I use the following to search for strings within the stored procedures of a specific database:
USE DBname
SELECT Name
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%xxx%'
Is it easy to amend the above so that it searches Table names in a specific db "DBname" ?
I'm using this and works fine
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%%'
select name
from DBname.sys.tables
where name like '%xxx%'
and is_ms_shipped = 0; -- << comment out if you really want to see them
If you want to look in all tables in all Databases server-wide and get output you can make use of the undocumented sp_MSforeachdb procedure:
sp_MSforeachdb 'SELECT "?" AS DB, * FROM [?].sys.tables WHERE name like ''%Table_Names%'''
You can also use the Filter button to filter tables with a certain string in it.
You can do the same with stored procedures and views.
I am assuming you want to pass the database name as a parameter and not just run:
SELECT *
FROM DBName.sys.tables
WHERE Name LIKE '%XXX%'
If so, you could use dynamic SQL to add the dbname to the query:
DECLARE #DBName NVARCHAR(200) = 'YourDBName',
#TableName NVARCHAR(200) = 'SomeString';
IF NOT EXISTS (SELECT 1 FROM master.sys.databases WHERE Name = #DBName)
BEGIN
PRINT 'DATABASE NOT FOUND';
RETURN;
END;
DECLARE #SQL NVARCHAR(MAX) = ' SELECT Name
FROM ' + QUOTENAME(#DBName) + '.sys.tables
WHERE Name LIKE ''%'' + #Table + ''%''';
EXECUTE SP_EXECUTESQL #SQL, N'#Table NVARCHAR(200)', #TableName;
If you prefer case-insensitive searching:
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME ILIKE '%%'
or
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE Lower(TABLE_NAME) LIKE Lower('%%')
Adding on to #[RichardTheKiwi]'s answer.
Whenever I search for a list of tables, in general I want to select from all of them or delete them. Below is a script that generates those scripts for you.
The generated select script also adds a tableName column so you know what table you're looking at:
select 'select ''' + name + ''' as TableName, * from ' + name as SelectTable,
'delete from ' + name as DeleteTable
from sys.tables
where name like '%xxxx%'
and is_ms_shipped = 0;
you can also use the show command.
show tables like '%tableName%'
I want to post a simple solution for every schema you've got. If you are using MySQL DB, you can simply get from your schema all the table's name and add the WHERE-LIKE condition on it. You also could do it with the usual command line as follows:
SHOW TABLES WHERE tables_in_<your_shcema_name> LIKE '%<table_partial_name>%';
where tables_in_<your_shcema_name> returns the column's name of SHOW TABLES command.
You can use below :
Select * from sys.tables where name like '%yourtablename%'
This will working fine....
SELECT * FROM sys.TABLES
WHERE name LIKE '%%'

SQL Query Replace All

I want to modify the following query:
UPDATE wp_posts
SET post_content =
REPLACE(post_content, 'http://oldlink.com', 'http://newlink.com');
To be something that goes through all tables, columns and values. Something similar to this (but this doesn't work):
UPDATE * SET *= REPLACE(*, 'http://oldlink.com', 'http://newlink.com');
I want to replace every instance of my old link to my new link in my database. Is there any way to do this?
UPDATE
Sorry, I forgot to mention, it's MySQL. I'm currently going through all the answers and I'll be back and let you know what worked. Thanks everyone!
UPDATE 2
Hi guys (and girls), I decided to just dump the database and do manual search and replace (with TextWrangler). As this isn't (currently) a large DB, it's probably the easiest way.
Here is one that works on SQL Server -- does something like this work for you?
Search and Replace SQL Server data in all columns, of all tables
Here's a stored procedure named, SearchAndReplace, that searches
through all the character columns of all tables in the current
database, and replaces the given string with another user provided
string.
This mssql script will whine a bit if there is a computed column in a table, but it will still execute:
DECLARE #searchvalue varchar(100)
DECLARE #newvalue varchar(100)
SET nocount off
SET #searchvalue = 'http://oldlink.com'
SET #newvalue = 'http://newlink.com'
SELECT * into #t FROM
(
SELECT 'update [' + a.TABLE_name + '] SET ['+ column_name+ ']=''' + #newvalue + '''
where [' +a.column_name+
']='''+#searchvalue +'''' sqlstring
FROM INFORMATION_SCHEMA.COLUMNS a
join
INFORMATION_SCHEMA.TABLES b
ON a.TABLE_name = b.TABLE_name
and b.TABLE_type = 'base table'
WHERE data_type in ('varchar', 'char', 'nvarchar')
and character_maximum_length >= len(#newvalue)
) a
DECLARE #sqlstring as nvarchar(500)
DECLARE SqlCursor CURSOR FAST_FORWARD FOR
SELECT sqlstring FROM #t
OPEN SqlCursor
FETCH NEXT FROM SqlCursor
INTO #sqlstring
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC(#sqlstring)
FETCH NEXT FROM SqlCursor
INTO #sqlstring
END
CLOSE SqlCursor
DEALLOCATE SqlCursor
DROP TABLE #t
You didn't mention the database. I currently use Sybase ASA, where you cannot do this literally but it can be done by checking the column names from a join of systable and syscolumn and then using execute immediate