SQL Query to delete data from tables defined in table - sql

I'm trying to delete data from a number of tables in my SQL base.
In the database I have a table called company which contains the names of each table that I need to delete data from.
lets assume that I have 3 companies in my company table.
What I want to do is delete all records in some certain tables in each company.
So, in the company table I have the following 3 records:
1 2 3
There are also the following tables in the database which depicts each company's scanned documents.
dbo.1.documents
dbo.2.documents
dbo.3.documents
What I am trying to do is to create a SQL query that will run through the dbo.company table and clear the document tables based on the company names found there.
This is my code:
DECLARE #MyCursor CURSOR;
DECLARE #MyField varchar;
BEGIN
SET #MyCursor = CURSOR FOR
select top 1000 [Name] from dbo.Company
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
delete * from 'dbo.'+#MyField+'$documents'
FETCH NEXT FROM #MyCursor
INTO #MyField
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
I am not sure how the syntax should go but I imagine it is something like this.
Anybody care to chip in on how I can dynamically delete the data based on the records in the dbo.company.name?

Use dynamic sql.
Replace the delete-statement with code below (the declare can be done at the start):
DECLARE #sql NVARCHAR(1000)
SET #sql = N'delete from dbo.'+CONVERT(VARCHAR,#MyField)+'documents'
EXEC sp_executesql #sql

You can leverage dynamic sql a little differently and avoid all the hassle and overhead of creating a cursor for this. I am using the values in your table to generate a number of delete statements and then executing them. This is a lot less effort to code and eliminates that nasty cursor.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'delete dbo.[' + c.Name + '$documents];'
from dbo.Company
select #SQL --uncomment the line below when you are satisfied the dynamic sql is correct
--exec sp_executesql #sql

Related

Iterate Query Result in SQL Server Stored Procedure

I have a stored procedure where I need to query a table that contains another query that I then need to execute, get the results, and store those results in another table. I will not know what, or how many, columns are returned from this query, but I must be able to map the unknown columns to columns in my results table. I do know that the query can contain anywhere from 1 to 20 columns which need to map to my results table as RSLT_1 up to RSLT_20.
For Example, let's say the query returns 5 columns. I need to iterate over the results and map column1 to RSLT_1, column2 to RSLT_2, etc. Then store those results in my result table
I have this logic already written in C# which was trivial since I can loop over columns to determine how many exist. I don't know how to do that in a stored procedure. Any ideas?
I cannot write you a complete answer, because I don't know your queries/tables. Here main lines of what I'm thinking about. You have to complete for your needs. But keep in mind, cursor is slow and generally not recommended in production.
select * into #tmp from <sourceQuery>
declare #columnName varchar(100)
declare #sql NVARCHAR(MAX)
declare c cursor for
select name from tempdb.sys.columns where object_id = object_id('tempdb..#tmp')
open c
fetch next from c into #columnName
while ##FETCH_STATUS = 0
begin
select #columnName
set #sql = N'insert into <targetTable> (valueColumn) select ' + #columnName + 'from #tmp'
exec #sql
fetch next from c into #columnName
end
close c
deallocate c
drop table #tmp

Copy SQL Server database for development but smaller

We have production database above 100Gig. I want to duplicate this database and give it to every developer to test its code, but the size is too large. Is there anyway I can backup just top 1000 rows with FK's and restore it to new DB? Or duplicate the DB first and delete all records from all tables, but keep 1000 rows with FK's or any other way to keep size below 5Gig.
I did search, but none of solutions were for tables having foreign keys.
Thanks,
Basheer
This the IDEA:
First:
Create new database:
Second:
Select small records only like:
select top 500 from allYourTables
then insert to each every table to your new Database Created.
Third:
Dump the new database and give to its every developer
Hope it helps:
Assuming that you have a new db_to_dev Database name and you are working to your current database:
This procedure will insert all the data from your working database, making sure that you had already a database created. db_to_dev:
Using Information_Schema you can select all your tables:
CREATE PROCEDURE PROC_TRANSFER_DATA #NUM_OF_RECORDS nvarchar(255) as
BEGIN
SET NOCOUNT ON;
DECLARE #message varchar(80), #tablename nvarchar(50);
Declare #sqlstmt nvarchar(255);
PRINT '-------- List of tables --------';
DECLARE Schema_cursor CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
OPEN Schema_cursor
FETCH NEXT FROM Schema_cursor INTO #tablename
IF ##FETCH_STATUS <> 0
PRINT ' <<None>>'
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #message = ' ' + #tablename
set #sqlstmt = 'select top ' + #NUM_OF_RECORDS + ' * into [db_to_dev].[dbo].['+ #tablename +'] from ' + #tablename;
EXEC sp_executesql #sqlstmt
PRINT #message
FETCH NEXT FROM Schema_cursor INTO #tablename
END
CLOSE Schema_cursor
DEALLOCATE Schema_cursor
END
To use:
With an option parameter:
EXEC PROC_TRANSFER_DATA '500'
Parameter value is depend on you if how many records you want to transfer into your new database db_to_dev.
This Stored Proc is tested.
Good luck
There are a number of projects on github which seek to do exactly that: make a subset that preserves referential integrity. Here is one such project:
https://github.com/18F/rdbms-subsetter

Execute dynamic select query stored in a table

I have stored select statements in a table column named RuleSql. In the future the table size will go large, so how can I execute all the stored select statements at the same time to get the result?
I have used:
EXEC sp_executesql
But it is not helpful for me.
It's very poor practice storing SQL code in a table. Have you looked at views, stored procedures or inline table-valued functions?
Anyway, to execute the stored SQL in a table you would do something like this....
DECLARE #Sql NVARCHAR(MAX);
SELECT TOP 1 #Sql = RuleSql
FROM TableName --<-- table where sql is stored
WHERE <Some Condition>
Exec sp_executesql #Sql
Just saw your edit. To execute all the queries at once you would use a cursor something like.....
DECLARE #Sql NVARCHAR(MAX);
DECLARE Cur CURSOR LOCAL FAST_FORWARD FOR
SELECT RuleSql
FROM TableName --<-- table where sql is stored
OPEN Cur
FETCH NEXT FROM Cur INTO #Sql
WHILE (##FETCH_STATUS = 0)
BEGIN
Exec sp_executesql #Sql
FETCH NEXT FROM Cur INTO #Sql
END
CLOSE Cur
DEALLOCATE Cur;
If you want this same information but for the whole database (all tables of a database) and create a table wit results you can use followin

Use “insert into” only with databases that has a certain table ( SQL Server 2008 R2 )

I need to do a "log" with all the information of a certain table, of all databases, inside a new table that I will create (With the same structure).
But not all databases has this table.
I could make a query to find all databases that has this table I want:
SELECT name
FROM sys.databases
WHERE CASE
WHEN state_desc = 'ONLINE'
THEN OBJECT_ID(QUOTENAME(name) + '.[dbo].[tblLogdiscador]', 'U')
END IS NOT NULL
It will only list the databases with this table I want to log. But now I need to do a loop, to pass by all databases, inserting the information of the "tbllogdiscador" into the table I created. I was thinking in SP_MSFOREACHDB but I see a lot of people saying to not use it.
How can I loop trough all databases that has the table, and if it has, insert into the new log table??
The code below is not helping me:
exec sp_msforeachdb 'if ((select count(*)
from [?].sys.tables Where name in(''tbllogdiscador''))=1)
begin
insert into [The new tbl log]
select * from ?.dbo.tbllog
end
I'm trying to use a cursor, but i'm having problems.
Any Ideas how to do this with WHILE?
To do what you are thinking, you need some kind of process flow logic (A cursor seems to be the most fitting choice), and dynamic sql.
So the high level is we need to get all of the DB names, put them into the cursor, and then use the cursor to execute the dynamic sql statement where you test to see of the table exists, and pull the records if so.
Ok so here is an example cursor that loops through the DBs on a server looking for a particular table name, and if it exists, does something (you'll have to do the sql for #Sql2):
declare #DBName varchar(256)
declare #SQL1 nvarchar(max)
declare #Sql2 nvarchar(max)
DECLARE db_cursor CURSOR FOR
SELECT name
FROM sys.databases
WHERE state_desc = 'ONLINE'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #DBName
WHILE ##FETCH_STATUS = 0
Begin
set #SQL1 = 'Select Name from ' + #DBName + '.sys.objects where name = ''tblLogdiscador'' '
set #SQL2 = --Your select and insert statement selecting from #DBName + 'dbo.tbllogdiscador'
if exists(exec sp_executesql #Sql1)
begin
exec sp_executesql #sql2
end
FETCH NEXT FROM db_cursor INTO #DBName
end
close db_cursor
deallocate db_cursor

How do I go through a cursor to perform logic on multiple tables? (The table names are in the cursor)

I get the feeling this is pretty basic database work, but it isn't for me. I'm trying to get a list of all of my tombstone tables from system tables and store the results in a cursor. I'm then trying to perform some logic on each of those tables I'm having trouble doing so.
Any help would be greatly appreciated.
Here is the error I get:
Must declare the table variable "#tablename"
Here is the code:
declare tombstonetables cursor for
(select name from sys.objects
where
name like'%tombstone%'
and type = 'U'--for user_table
)
Print 'Begin purging tombstone tables'
declare #tablename varchar(250)
open tombstonetables
fetch next from tombstonetables into #tablename
WHILE ##FETCH_STATUS = 0
begin
select * from #tablename--real logic goes here later
fetch next from tombstonetables into #tablename
end
close tombstonetables
deallocate tombstonetables
Looks like you need to use Dynamic SQL
Here is a reference to a simple walk through http://www.mssqltips.com/tip.asp?tip=1160
You will probably need to make use of sp_executesql
Here is a simple example of using Dynamic SQL with your example
DECLARE #DynamicSQL nvarchar(100)
WHILE ##FETCH_STATUS = 0
begin
SET #DynamicSQL = 'select * from ' + #tablename --real logic goes here later
EXEC #DynamicSQL
fetch next from tombstonetables into #tablename
end