DELETE FROM AllTables Where ColumnName="Some Text" - sql

I'm working with some databases and I have quite a few items I need to remove from them. There are about 300 or so tables in each database and I am trying to find a way to drop the rows that contain the string I need to remove.
DELETE FROM TableName WHERE ColumnName='Some String'
Works just fine, but I do not want to run that for each table. I'm hoping there is a way to do something like:
DELETE FROM * WHERE ColumnName='Some String'
I have been searching around on Google and have come accross several articles on how to drop all of the data in all the tables, which is not what I am trying to accomplish.
I am using MS SQL Server 2014.
I am still somewhat new to SQL and I don't know if there is already a way to this and I am just not using the write search terms to find it.
Thank you for your assistance.

This works for other databases, too - on other databases, you only have to change the syntax for the concatenation from + to || and change schema and name of the COLUMNS system view / table.
Run the query to a report on file. Remove any headers/footers. Then, run that file as a SQL script.
SELECT
'DELETE FROM ' + table_catalog
+ '.' + table_schema
+ '.' + table_name
+ ' WHERE ' + column_name
+ ' = ''Some String'';'
FROM information_schema.columns
WHERE UPPER(column_name) = 'NAME'
;
My database, which happens to be Vertica, returns:
DELETE FROM gpb.agreement_type WHERE name = 'Some String';
DELETE FROM gpb.product WHERE name = 'Some String';
DELETE FROM gpb.account_type WHERE name = 'Some String';
DELETE FROM gpb.document_type WHERE name = 'Some String';
DELETE FROM gpb.transaction_type WHERE name = 'Some String';
DELETE FROM gpb.account WHERE name = 'Some String';
DELETE FROM public.people_with_dupes WHERE name = 'Some String';
DELETE FROM public.people WHERE name = 'Some String';

There is an undocumented (but not unknown) stored procedure called sp_MSforeachtable.
exec sp_MSforeachtable 'DELETE FROM ? WHERE ColumnName = 'Some String';

TRY: You can use this technique to get rid from the tedious job of typing code for every table. You can first retrieve all the objects which have that <column_name> and then create a loop with delete statement. Please change <column_name> with your real column name.
Please try it, I am sure it will work for you:
select id = identity(int, 1, 1), o.name INTO #object_name
from sys.objects o
inner join sys.columns c on c.object_id = o.object_id
where type = 'u' and c.name = <column_name>
declare #i int = 1, #j int = 0, #sql varchar(500)
select #j = count(*) from #object_name
while (#i <= #j)
begin
declare #tbl_name varchar(100)
select #tbl_name = name from #object_name where id = #i
set #sql = 'delete from ' + #tbl_name + ' where <column_name> = <some_string>'
--print(#sql)
exec(#sql)
set #i = #i+1
end

Delete column from single table :
ALTER TABLE table_name DROP COLUMN column_name
Delete column from multiple table :
DECLARE #SQL VARCHAR(MAX)
SELECT #SQL += 'Alter table ' + Quotename(table_catalog)
+ '.' + Quotename(table_schema) + '.'
+ Quotename(TABLE_NAME) + ' DROP column '
+ Quotename(column_name) + ';'
FROM information_schema.columns where COLUMN_NAME = 'your_column_name' --
EXEC Sp_executesql #sql

Related

Add new column to all tables in database

I'm trying to figure out if there's a quick way or single query to add a new column to all tables in database.
Right now I'm doing this for each table
ALTER TABLE [dbo].[%TABLE_NAME%] ADD %COLUMN_NAME% DATATYPE NOT NULL DEFAULT %VALUE%;
Is there a procedure or query I can make in AzureDataStudio to add a new column to all tables with the same name and default value.
select 'ALTER TABLE ' + QUOTENAME(SCHEMA_NAME([schema_id])) + '.' + QUOTENAME([name])
+ ' ADD %COLUMN_NAME% DATATYPE NOT NULL DEFAULT %VALUE%;'
from sys.tables
Create the statements you need with the above then run them.
I'd personally create a loop with dynamic SQL which gets executed as it is ran. The code below creates a temp table which is utilized for the loop which will iterate through each table listed in the temp table based on a calculated row number. The dynamic SQL is then set and executed.
Once you make the necessary changes, putting in your database name, column name, data type, and default value and you are satisfied with the results that get printed, you can un-comment the EXECUTE(#SQL) and re-run the script and it will add the new column to all your tables.
USE [INSERT DATABASE NAME HERE]
GO
IF OBJECT_ID(N'tempdb..#TempSysTableNames') IS NOT NULL
BEGIN
DROP TABLE #TempSysTableNames
END;
DECLARE #ColumnName VARCHAR(250) = 'INSERT COLUMN NAME HERE'
,#DataType VARCHAR(250) = 'INSERT DATA TYPE HERE'
,#DefaultValue VARCHAR(250) = 'INSERT DEFAULT VALUE HERE'
,#SQL VARCHAR(8000)
,#MaxRowNum INT
,#I INT = 1;
SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME([object_id],DB_ID()) + '].[' + name + ']' AS [name]
,ROW_NUMBER() OVER (ORDER BY [create_date]) AS RowNum
INTO #TempSysTableNames
FROM sys.tables
WHERE [type] = 'U';
SET #MaxRowNum = (SELECT MAX(RowNum)
FROM #TempSysTableNames);
WHILE (#I <= #MaxRowNum)
BEGIN
SET #SQL = (SELECT 'ALTER TABLE ' + [name] + ' ADD ' + #ColumnName + ' ' + #DataType + ' NOT NULL DEFAULT ' + #DefaultValue + ';'
FROM #TempSysTableNames
WHERE RowNum = #I);
PRINT(#SQL);
--EXECUTE(#SQL);
SET #I += 1;
END;

Delete data form multiple unknown tables in SQL Server?

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)

Is there a way to remove '_' from column name while selecting * in sql statement?

My table has all the column names
(There are more than 80 columns, I can't change the column names now)
in the format of '_'. Like First_Name, Last_Name,...
So i want to use select * from table instead
of using AS.
I want to select them by removing '_' in one statement. Anyway i can do it?
something like Replace(coulmnName, '_','') in select statement ?
Thanks
You can simply rename the column in your query. For example:
SELECT FIRST_NAME [First Name],
LAST_NAME [Last Name]
FROM UserTable
You can also use the AS keyword but this is optional. Also note that if you don't want to do this on every query you can use this process to create a view with renamed columns. Then you can use SELECT * the way you want to (although this is considered a bad idea for many reasons).
Best of luck!
Alternative - Map In The Client Code:
One other alternative is to do the mapping in the client code. This solution is going to depend greatly on your ORM. Most ORM's (such as LINQ or EF) will allow you to remap. If nothing else you could use AutoMapper or similar to rename the columns on the client using convention based naming.
You can't do this in a single statement unless you're using dynamic SQL. If you're just trying to generate code, you can run a query against Information_Schema and get the info you want ...
DECLARE #MaxColumns INT
DECLARE #TableName VARCHAR(20)
SET #TableName = 'Course'
SELECT #MaxColumns = MAX(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName
SELECT Col
FROM
(
SELECT 0 Num, 'SELECT' Col
UNION
SELECT ROW_NUMBER() OVER (PARTITION BY TABLE_NAME ORDER BY ORDINAL_POSITION) Num, ' [' + COLUMN_NAME + '] AS [' + REPLACE(COLUMN_NAME, '_', '') + ']' + CASE WHEN ORDINAL_POSITION = #MaxColumns THEN '' ELSE ',' END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableName
UNION
SELECT #MaxColumns + 1 Num, 'FROM ' + #TableName
) s
ORDER BY num
The question intrigued me and I did find one way. It makes it happen but if you just wanted to give a lot of aliases one time in one query I wouldn't recommend it though.
First I made a stored procedure that extracts all the column names and gives them an alias without '_'.
USE [DataBase]
GO
IF OBJECT_ID('usp_AlterColumnDisplayName', 'P') IS NOT NULL
DROP PROCEDURE usp_AlterColumnDisplayName
GO
CREATE PROCEDURE usp_AlterColumnDisplayName
#TableName VARCHAR(50)
,
#ret nvarchar(MAX) OUTPUT
AS
Select #ret = #ret + [Column name]
From
(
SELECT ([name] + ' AS ' + '[' + REPLACE([name], '_', ' ') + '], ') [Column name]
FROM syscolumns
WHERE id =
(Select id
From sysobjects
Where type = 'U'
And [name] = #TableName
)
) T
GO
Then extract that string and throw it into another string with a query-structure.
Execute that and you are done.
DECLARE #out NVARCHAR(MAX), #DesiredTable VARCHAR(50), #Query NVARCHAR(MAX)
SET #out = ''
SET #DesiredTable = 'YourTable'
EXEC usp_AlterColumnDisplayName
#TableName = #DesiredTable,
#ret = #out OUTPUT
SET #out = LEFT(#out, LEN(#out)-1) --Removing trailing ', '
SET #Query = 'Select ' + #out + ' From ' + #DesiredTable + ' WHERE whatever'
EXEC sp_executesql #Query
If you just wanted to give a lot of aliases at once without sitting and typing it out for 80+ columns I would rather suggest doing that with one simple SELECT statement, like the one in the sp, or in Excel and then copy paste into your code.

SQL query to return all rows where one or more of the fields contains a certain value

Is it possible to run a select on a table to quickly find out if any (one or more) of the fields contain a certain value?
Or would you have to write out all of the column names in the where clause?
As others have said, you're likely going to have to write all the columns into your WHERE clause, either by hand or programatically. SQL does not include functionality to do it directly. A better question might be "why do you need to do this?". Needing to use this type of query is possibly a good indicator that your database isn't properly normalized. If you tell us your schema, we may be able to help with that problem too (if it's an actual problem).
Dig this... It will search on all the tables in the db, but you can mod it down to just one table.
/*This script will find any text value in the database*/
/*Output will be directed to the Messages window. Don't forget to look there!!!*/
SET NOCOUNT ON
DECLARE #valuetosearchfor varchar(128), #objectOwner varchar(64)
SET #valuetosearchfor = '%staff%' --should be formatted as a like search
SET #objectOwner = 'dbo'
DECLARE #potentialcolumns TABLE (id int IDENTITY, sql varchar(4000))
INSERT INTO #potentialcolumns (sql)
SELECT
('if exists (select 1 from [' +
[tabs].[table_schema] + '].[' +
[tabs].[table_name] +
'] (NOLOCK) where [' +
[cols].[column_name] +
'] like ''' + #valuetosearchfor + ''' ) print ''SELECT * FROM [' +
[tabs].[table_schema] + '].[' +
[tabs].[table_name] +
'] (NOLOCK) WHERE [' +
[cols].[column_name] +
'] LIKE ''''' + #valuetosearchfor + '''''' +
'''') as 'sql'
FROM information_schema.columns cols
INNER JOIN information_schema.tables tabs
ON cols.TABLE_CATALOG = tabs.TABLE_CATALOG
AND cols.TABLE_SCHEMA = tabs.TABLE_SCHEMA
AND cols.TABLE_NAME = tabs.TABLE_NAME
WHERE cols.data_type IN ('char', 'varchar', 'nvchar', 'nvarchar','text','ntext')
AND tabs.table_schema = #objectOwner
AND tabs.TABLE_TYPE = 'BASE TABLE'
ORDER BY tabs.table_catalog, tabs.table_name, cols.ordinal_position
DECLARE #count int
SET #count = (SELECT MAX(id) FROM #potentialcolumns)
PRINT 'Found ' + CAST(#count as varchar) + ' potential columns.'
PRINT 'Beginning scan...'
PRINT ''
PRINT 'These columns contain the values being searched for...'
PRINT ''
DECLARE #iterator int, #sql varchar(4000)
SET #iterator = 1
WHILE #iterator <= (SELECT Max(id) FROM #potentialcolumns)
BEGIN
SET #sql = (SELECT [sql] FROM #potentialcolumns where [id] = #iterator)
IF (#sql IS NOT NULL) and (RTRIM(LTRIM(#sql)) <> '')
BEGIN
--SELECT #sql --use when checking sql output
EXEC (#sql)
END
SET #iterator = #iterator + 1
END
PRINT ''
PRINT 'Scan completed'
I think you'd need to list all the columns in the where clause. I'm far from a SQL wizard though...maybe someone else knows a way.
you will have to write it out
Of course you have to write out all columns you want to use as a criteria.
If you add what programming language you are using and in what type of environment you working we can give you a clue or solution of how to do it dynamically.
I think your question really was how to do this dynamically depending of what the user of your program fill in in the "search"-form.. Im right?
If not, then.. Give us more information. ;)

Drop all tables whose names begin with a certain string

How can I drop all tables whose names begin with a given string?
I think this can be done with some dynamic SQL and the INFORMATION_SCHEMA tables.
You may need to modify the query to include the owner if there's more than one in the database.
DECLARE #cmd varchar(4000)
DECLARE cmds CURSOR FOR
SELECT 'drop table [' + Table_Name + ']'
FROM INFORMATION_SCHEMA.TABLES
WHERE Table_Name LIKE 'prefix%'
OPEN cmds
WHILE 1 = 1
BEGIN
FETCH cmds INTO #cmd
IF ##fetch_status != 0 BREAK
EXEC(#cmd)
END
CLOSE cmds;
DEALLOCATE cmds
This is cleaner than using a two-step approach of generate script plus run. But one advantage of the script generation is that it gives you the chance to review the entirety of what's going to be run before it's actually run.
I know that if I were going to do this against a production database, I'd be as careful as possible.
Edit Code sample fixed.
SELECT 'DROP TABLE "' + TABLE_NAME + '"'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
This will generate a script.
Adding clause to check existence of table before deleting:
SELECT 'IF OBJECT_ID(''' +TABLE_NAME + ''') IS NOT NULL BEGIN DROP TABLE [' + TABLE_NAME + '] END;'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
This will get you the tables in foreign key order and avoid dropping some of the tables created by SQL Server. The t.Ordinal value will slice the tables into dependency layers.
WITH TablesCTE(SchemaName, TableName, TableID, Ordinal) AS
(
SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName,
OBJECT_NAME(so.object_id) AS TableName,
so.object_id AS TableID,
0 AS Ordinal
FROM sys.objects AS so
WHERE so.type = 'U'
AND so.is_ms_Shipped = 0
AND OBJECT_NAME(so.object_id)
LIKE 'MyPrefix%'
UNION ALL
SELECT OBJECT_SCHEMA_NAME(so.object_id) AS SchemaName,
OBJECT_NAME(so.object_id) AS TableName,
so.object_id AS TableID,
tt.Ordinal + 1 AS Ordinal
FROM sys.objects AS so
INNER JOIN sys.foreign_keys AS f
ON f.parent_object_id = so.object_id
AND f.parent_object_id != f.referenced_object_id
INNER JOIN TablesCTE AS tt
ON f.referenced_object_id = tt.TableID
WHERE so.type = 'U'
AND so.is_ms_Shipped = 0
AND OBJECT_NAME(so.object_id)
LIKE 'MyPrefix%'
)
SELECT DISTINCT t.Ordinal, t.SchemaName, t.TableName, t.TableID
FROM TablesCTE AS t
INNER JOIN
(
SELECT
itt.SchemaName AS SchemaName,
itt.TableName AS TableName,
itt.TableID AS TableID,
Max(itt.Ordinal) AS Ordinal
FROM TablesCTE AS itt
GROUP BY itt.SchemaName, itt.TableName, itt.TableID
) AS tt
ON t.TableID = tt.TableID
AND t.Ordinal = tt.Ordinal
ORDER BY t.Ordinal DESC, t.TableName ASC
On Oracle XE this works:
SELECT 'DROP TABLE "' || TABLE_NAME || '";'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'
Or if you want to remove the constraints and free up space as well, use this:
SELECT 'DROP TABLE "' || TABLE_NAME || '" cascade constraints PURGE;'
FROM USER_TABLES
WHERE TABLE_NAME LIKE 'YOURTABLEPREFIX%'
Which will generate a bunch of DROP TABLE cascade constraints PURGE statements...
For VIEWS use this:
SELECT 'DROP VIEW "' || VIEW_NAME || '";'
FROM USER_VIEWS
WHERE VIEW_NAME LIKE 'YOURVIEWPREFIX%'
EXEC sp_MSforeachtable 'if PARSENAME("?",1) like ''%CertainString%'' DROP TABLE ?'
Edit:
sp_MSforeachtable is undocumented hence not suitable for production because it's behavior may vary depending on MS_SQL version.
Here is my solution:
SELECT CONCAT('DROP TABLE `', TABLE_NAME,'`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'TABLE_PREFIX_GOES_HERE%';
And of course you need to replace TABLE_PREFIX_GOES_HERE with your prefix.
I saw this post when I was looking for mysql statement to drop all WordPress tables based on #Xenph Yan here is what I did eventually:
SELECT CONCAT( 'DROP TABLE `', TABLE_NAME, '`;' ) AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'wp_%'
this will give you the set of drop queries for all tables begins with wp_
CREATE PROCEDURE usp_GenerateDROP
#Pattern AS varchar(255)
,#PrintQuery AS bit
,#ExecQuery AS bit
AS
BEGIN
DECLARE #sql AS varchar(max)
SELECT #sql = COALESCE(#sql, '') + 'DROP TABLE [' + TABLE_NAME + ']' + CHAR(13) + CHAR(10)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #Pattern
IF #PrintQuery = 1 PRINT #sql
IF #ExecQuery = 1 EXEC (#sql)
END
Xenph Yan's answer was far cleaner than mine but here is mine all the same.
DECLARE #startStr AS Varchar (20)
SET #startStr = 'tableName'
DECLARE #startStrLen AS int
SELECT #startStrLen = LEN(#startStr)
SELECT 'DROP TABLE ' + name FROM sysobjects
WHERE type = 'U' AND LEFT(name, #startStrLen) = #startStr
Just change tableName to the characters that you want to search with.
This worked for me.
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += '
DROP TABLE '
+ QUOTENAME(s.name)
+ '.' + QUOTENAME(t.name) + ';'
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE t.name LIKE 'something%';
PRINT #sql;
-- EXEC sp_executesql #sql;
select 'DROP TABLE ' + name from sysobjects
where type = 'U' and sysobjects.name like '%test%'
-- Test is the table name
SELECT 'if object_id(''' + TABLE_NAME + ''') is not null begin drop table "' + TABLE_NAME + '" end;'
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '[prefix]%'
I had to do a slight derivation on Xenph Yan's answer I suspect because I had tables not in the default schema.
SELECT 'DROP TABLE Databasename.schema.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'strmatch%'
In case of temporary tables, you might want to try
SELECT 'DROP TABLE "' + t.name + '"'
FROM tempdb.sys.tables t
WHERE t.name LIKE '[prefix]%'
I would like to post my proposal of the solution which DROP (not just generate and select a drop commands) all tables based on the wildcard (e.g. "table_20210114") older than particular amount of days.
DECLARE
#drop_command NVARCHAR(MAX) = '',
#system_time date,
#table_date nvarchar(8),
#older_than int = 7
Set #system_time = (select getdate() - #older_than)
Set #table_date = (SELECT CONVERT(char(8), #system_time, 112))
SELECT #drop_command += N'DROP TABLE ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME([Name]) + ';'
FROM <your_database_name>.sys.tables
WHERE [Name] LIKE 'table_%' AND RIGHT([Name],8) < #table_date
SELECT #drop_command
EXEC sp_executesql #drop_command
If your query returns more than one line, you can collect the results and merge them into a query.
declare #Tables as nvarchar(max) = '[schemaName].['
select #Tables =#Tables + TABLE_NAME +'],[schemaName].['
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
AND TABLE_SCHEMA = 'schemaName'
AND TABLE_NAME like '%whateverYourQueryIs%'
select #Tables = Left(#Tables,LEN(#Tables)-13) --trying to remove last ",[schemaName].[" part, so you need to change this 13 with actual lenght
--print #Tables
declare #Query as nvarchar(max) = 'Drop table ' +#Tables
--print #Query
exec sp_executeSQL #Query
Try following code:
declare #TableLst table(TblNames nvarchar(500))
insert into #TableLst (TblNames)
SELECT 'DROP TABLE [' + Table_Name + ']'
FROM INFORMATION_SCHEMA.TABLES
WHERE Table_Name LIKE 'yourFilter%'
WHILE ((select COUNT(*) as CntTables from #TableLst) > 0)
BEGIN
declare #ForExecCms nvarchar(500) = (select top(1) TblNames from #TableLst)
EXEC(#ForExecCms)
delete from #TableLst where TblNames = #ForExecCms
END
This SQL script is executed without using a cursor.