SQL delete all from all if column A exists and equals B - mysql

How can I delete all records from all tables in a database, where the table has a column called systemid where systemid does not equal 1 or 2?
So I need to see if the table contains a certain column name, and if yes, check value of that column for all records, if not 1 or 2, delete. On all tables in the db.
Trying to clean-up a development db.
--- UPDATE ---
I found this SO thread: SQL Server : check if table column exists and remove rows
Which details the following:
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1')
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1' AND COLUMN_NAME = 'COL1')
delete TAB1 where COL1 not in (select COL2 from TAB2);
but I can't for the life of me correctly from a SQL query that can do what I wan to achieve due to both lack of knowledge and experience. Could anyone please provide a sample code with an explanation?
Thank you overflowers!

DECLARE #TableName VARCHAR(128);
DECLARE #MyColumn VARCHAR(128);
SET #MyColumn = 'MyColumnName'
DECLARE MyCursor CURSOR FOR
(SELECT OBJECT_NAME(c.id) as ObjectName
FROM dbo.syscolumns c
WHERE
OBJECTPROPERTY(c.id,'ISTABLE') = 1 --Search for tables only
AND c.name = #MyColumn)
OPEN MyCursor
FETCH NEXT FROM MyCursor into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC
(
'DELETE ' + #MyColumn
+' FROM ' + #TableName
+' WHERE ' + #MyColumn + ' not in (1,2)'
)
FETCH NEXT FROM MyCursor into #TableName
END
CLOSE MyCursor
DEALLOCATE MyCursor

Related

How to not show certain columns in MySQL? [duplicate]

when I do:
SELECT *
FROM SOMETABLE
I get all the columns from SOMETABLE, but I DON'T want the columns which are NULL (for all records). How do I do this?
Reason: this table has 20 columns, 10 of these are set but 10 of them are null for certain queries. And it is time consuming to type the columnnames....
Thanks,
Voodoo
SQL supports the * wildcard which means all columns. There is no wildcard for all columns except the ones you don't want.
Type out the column names. It can't be more work than asking questions on Stack Overflow. Also, copy & paste is your friend.
Another suggestion is to define a view that selects the columns you want, and then subsequently you can select * from the view any time you want.
It's possible to do, but kind of complicated. You can retrieve the list of columns in a table from INFORMATION_SCHEMA.COLUMNS. For each column, you can run a query to see if any non-null row exists. Finally, you can run a query based on the resulting column list.
Here's one way to do that, with a cursor:
declare #table_name varchar(256)
set #table_name = 'Airports'
declare #rc int
declare #query nvarchar(max)
declare #column_list varchar(256)
declare columns cursor local for select column_name
from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = #table_name
open columns
declare #column_name varchar(256)
fetch next from columns into #column_name
while ##FETCH_STATUS = 0
begin
set #query = 'select #rc = count(*) from ' + #table_name + ' where ' +
#column_name + ' is not null'
exec sp_executesql #query = #query, #params = N'#rc int output',
#rc = #rc output
if #rc > 0
set #column_list = case when #column_list is null then '' else
#column_list + ', ' end + #column_name
fetch next from columns into #column_name
end
close columns
deallocate columns
set #query = 'select ' + #column_list + ' from ' + #table_name
exec sp_executesql #query = #query
This runs on SQL Server. It might be close enough for Sybase. Hopefully, this demonstrates that typing out a column list isn't that bad :-)

Sql query to update table based on other tables

I have table structre like this:
Table MainTable
Columns:
Id INT,
TableName Varchar(50),
StartValue VARCHAR(50)
Here TableName column have names of all the tables present in the database
Now I need to update "StartValue" column in MainTable from corresponding tables. Any idea how to achieve this?
Example
MainTable
Id TableName StartValue
----------------------
1 table1 NULL
2 Table2 Null
I need to update StartValue column of MainTable by getting top 1 value from table name present in the tables
Means record 1 will get first value from table1 and record 2 will get first value from table2
Any idea how to achieve this?
try the following:
use DBName
go
declare cur cursor for
select Table_Name from MainTable
declare #var varchar(100)
open cur
fetch next from cur into #var
while ##FETCH_STATUS = 0
begin
declare #sql nvarchar(max)
set #sql = 'update MT set Start_Value = t.Start_Value from MainTable MT cross join ' + #var +' t where MT.Table_Name = ''' + #var +''''
exec sp_executesql #sql
fetch next from cur into #var
end
close cur
deallocate cur
--select * from MainTable
HTH!!!
Thanks.
If you are updating a column based on the value in another column, you could use DynamicSQL to build and then execute the query (probably using a CURSOR to loop through the rows of MainTable
DECLARE cur1 CURSOR FOR SELECT TABLENAME FROM MAINTABLE
OPEN cur1
FETCH NEXT FROM cur1INTO #TABLENAMEWHILE ##FETCH_STATUS = 0
BEGIN
SET #DYNSQL = 'UPDATE MAINTABLE SET STARTVALUE = SELECT TOP 1 STARTVALUE FROM ' + #TableName + ' WHERE
EXEC sp_executesql #DYNSQL
This is just one approach. Caveat regarding the use of cursors and DynamicSQL as always applies

Get count of NULL records in all MySQL tables based on particular field name

I'm using MySQL and we use a Deleted column to do "soft" deletes and keep history. I'm trying to write either a procedure or SQL statement which can get me the count from each table.
I believe this should be possible, as it somewhat reminds me of a SQL injection attack I've seen before. The difference is I want to use this for good purposes :)
I reworked the code shown there, but think my syntax may be off for MySQL; how can I correct this, or should I find a better way of accomplishing this? Below is reworked from the link (so pretty sure it doesn't follow the MySQL procedure syntax).
Here is what I have so far:
Set ansi_warnings off
Declare #T VARCHAR(255)
DECLARE Table_Cursor CURSOR FOR
Select
c.TABLE_NAME
from INFORMATION_SCHEMA.columns c, INFORMATION_SCHEMA.tables t
where
t.table_name = c.table_name
and t.table_type = 'BASE TABLE'
AND c.COLUMN_NAME = 'Deleted'
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO #T
WHILE(##FETCH_STATUS=0)
BEGIN
EXEC ( 'SELECT COUNT(*) AS ' + #T + 'Count FROM ' + #T + ' WHERE Deleted IS NULL' );
FETCH NEXT FROM Table_Cursor INTO #T
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor
I would guess that helps. Instead of
BEGIN
EXEC ( 'SELECT COUNT(*) AS ' + #T + 'Count FROM ' + #T + ' WHERE Deleted IS NULL' );
# would you not store that result somewhere?
FETCH NEXT FROM Table_Cursor INTO #T
END
just try
BEGIN
EXEC ( 'SELECT "#T" as tabname, COUNT(*) AS del_Count FROM ' + #T + ' WHERE Deleted IS NULL' );
# somewhere store the number and the tabname
FETCH NEXT FROM Table_Cursor INTO #T
END

Dropping all View under particular schema - SQL

How to drop all views under particular schema.
Ex: if I got below views in db.
[dbo].[view1]
[dbo].[veiw2]
[dbo].[view3]
[myView].[view1]
[myView].[veiw2]
[myView].[view3]
I just want to drop all views under schema myView all at a time.
Try this:
select 'drop view ' + QUOTENAME(sc.name) + '.' + QUOTENAME(obj.name) + ';'
from sys.objects obj
INNER JOIN sys.schemas sc
ON sc.schema_id = obj.schema_id
where obj.type='V'
and sc.name = 'myView';
I have tons of views (so, just aggregate drop query to one nvarchar(max) doesnt work - the query is truncated.) and i want to except some of views from deletion.
In this example, i want to drop every view from every schema beginnig with usr_* but not usr_test, usr_usr, usr_usr1, usr_usr2 and usr_usr3.
cursor is used because i dont care about few ms. This view cleaning query is used before integration tests, its not really speed-critical (and yet it perform really well)
declare drop_view_cursor cursor for
select 'drop view ' + QUOTENAME(sys.schemas.name) + '.' + QUOTENAME(sys.views.name) + ';'
from sys.views
inner join sys.schemas on sys.schemas.schema_id = sys.views.schema_id
where sys.schemas.schema_id in
(
select s.schema_id
from sys.schemas as s
where s.name like 'usr_%'
and s.name not in ('usr_test', 'usr_usr', 'usr_usr1', 'usr_usr2', 'usr_usr3')
)
declare #sql nvarchar(max)
open drop_view_cursor
fetch next from drop_view_cursor into #sql
while ##FETCH_STATUS = 0
begin
exec (#sql)
fetch next from drop_view_cursor into #sql
end
close drop_view_cursor
deallocate drop_view_cursor
This takes into account Schema, uses the system tables, and outputs to a variable that may then be executed. This way you don't have the problem of your Select truncating your script, because the Select and Print statements are limited on the length of what they may return.
The following runs in SQL Server 2008:
DECLARE #DropViewCommand nVarChar(MAX) = ''
SELECT #DropViewCommand = #DropViewCommand
+ 'DROP VIEW '+ QUOTENAME(S.Name) + '.' + QUOTENAME(V.name) + '; '
FROM sys.views as V
JOIN sys.schemas as S
ON S.schema_id = V.schema_id
WHERE S.name = 'dbo'--Selectively delete by Schema. Comment out to delete all views.
PRINT #DropViewCommand--See the command used in dropping all views (will be truncated in Select/Print, but not when Executing).
EXEC (#DropViewCommand)
Re-posting answer for those looking for specific solution. Put DROP view code in WHILE loop as shown below:
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
DECLARE #schema VARCHAR(128)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 ORDER BY [name])
SELECT #schema = (SELECT TOP 1 schema_name(schema_id) FROM sys.views WHERE [name] = #name)
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP VIEW [' + #schema + '].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped View: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 AND [name] > #name ORDER BY [name])
SELECT #schema = (SELECT TOP 1 schema_name(schema_id) FROM sys.views WHERE [name] = #name)
END
GO

Something equivalent to "SELECT * FROM (SELECT table_name FROM...)"?

This query runs, but it produces the name of a table as a result, rather than actually selecting from that table.
SELECT T.*
FROM (SELECT tablename
FROM ListOfTables
WHERE id = 0) AS T
where ListOfTables contains id=0, tablename='some_table', I want to return the same result set as if I had written this directly:
SELECT * FROM some_table
Is there a native way to do this in MySQL 5, or do I have to do in in the application?
To do this in MySQL, you need to create a prepared statement which you can only create from a user variable:
SELECT #tn := tablename FROM ListOfTables WHERE id = 0;
SET #qs = CONCAT('SELECT * FROM ', #tn);
PREPARE ps FROM #qs;
EXECUTE ps;
You need to use dynamic SQL to get this result (the below code assumes SQL Server, I can't speak for other RDBMS').
declare #tableName varchar(100)
declare #query varchar(500)
select #tableName = tablename
from ListOfTables
where id = 0
select #query = 'select * from ' + #tableName
exec (#query)
Almost the same as #Shark's answer, except you also quote the name of the table to avoid syntax errors.
-- Using variables just for better readability.
DECLARE #Name NVARCHAR(4000)
DECLARE #Query NVARCHAR(4000)
-- Get the relevant data
SET #Name = QUOTENAME(SELECT tablename FROM ListOfTables WHERE id=0)
-- Build query
SET #Query = 'SELECT * FROM ' + #Schema + '.' + #Name + ''
-- execute it.
EXEC(#Query)