in my project (automation-testing) I am adding a lot of data into my Database, which supposed to be deleted after running all scenarios, but in rare occasions when execution crashes I am sometimes left with records that were not deleted.
For this reason, I decided in addition store all records that were created into additional table, where I store:
new of the table where new record was inserted
name of the field used for where clause in delete statement
id of the record in its table
Now I am trying to select all records from table above, and use it to create delete queries.
Is it possible to do it in single query?
SELECT * FROM AutomationTestingData AS atd
DELETE FROM atd.TableName WHERE atd.DeleteByField = atd.RecordId
Any help would be appreciated, regards.
Hi if i understand all what you're trying i think this can respond :
SET NOCOUNT ON;
DECLARE #query varchar(4000);
PRINT '-------- Deleting rows --------';
DECLARE deleting_cursor CURSOR FOR
SELECT 'DELETE FROM ' + atd.TableName + ' WHERE ' + atd.DeleteByField + ' = ' + atd.RecordId + ';'
FROM AutomationTestingData AS atd
OPEN deleting_cursor
FETCH NEXT FROM deleting_cursor
INTO #query
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC(#Query)
FETCH NEXT FROM deleting_cursor
INTO #query
END
CLOSE deleting_cursor;
DEALLOCATE deleting_cursor;
CURSOR SQL : https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-2017
EXECUTE dynamic SQL Server : https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-2017
You could write a delete statement for each table, like this
delete from Company
where id in ( select RecordId from adt where adt.TableName = 'Company')
delete from PickListValues
where id in ( select RecordId from adt where adt.TableName = 'PickListValues')
Granted, its not really dynamic, but its still faster then dynamic sql and a cursor
Edit
IF you need it fully automatic, use dynamic sql like suggested by #pascalsanchez
I would alter the cursor however like this
declare deleting_cursor cursor for
select 'delete from ' + adt.TableName +
'where ' + adt.DeleteByField + ' in (select RecordID from adt where adt.TableName = ''' + adt.TableName + ''')
from AutomationTestingData AS atd
group by adt.TableName, adt.DeleteByField
you can use this syntax :
delete T1
from Table1 T1 join Table2.T2 on T1.SomeField=T2.SomeField
where Some Condition
Related
I am consistently running a report and creating tables for this report. Now other users are running thsi report as well. So I need users to be able to run stored procedure simultaniously without worry of overwriting tables. I tried using a simple temp table but I need the temporary table to work through out two "functions." One dynamic sql statement that creates a table and one dynamic sql statment thats table driven.
My primary issue is I want the table driven piece of code to be able to see the global temporary table variable but it does not. Is there a work around for this while still using temporary tables? is there a way to run both dynamic sql statements at once so the other type of temp table would work?
Any advice in the right direction is helpful. Thank you.
DECLARE #TmpGlobalTable varchar(255) = 'SomeText_' + convert(varchar(36),NEWID())
SELECT #SQL = #SQL +'
SELECT IDENTITY(INT) as idcol, date, Desc As [Description]
INTO [##' + #TmpGlobalTable + ']
FROM dbo.appendix
WHERE RecordStatus = 1
and casestatement from user input
'
print(#sql)
exec(#sql)
Declare #sql1 varchar(max) = ''
SELECT #SQL1 = #SQL1 +'
insert into dbo.'+#table+'
select ''1'', '''+date+''' as Sequence, Description as Description_color, buyer, seller, price, option
from '+#ClientTable+'
where isnull('+Seq+',9999) <= cutoffvalue
group by description , buyer, seller, price, option
'
from
[##' + #TmpGlobalTable + ']
print(#sql1)
exec(#sql1)
EXEC ('DROP TABLE [##' + #TmpGlobalTable + ']')
PRINT 'Dropped Table ' + #TmpGlobalTable
I have filtering SQL that returns query with uncertain number of columns, and want to use results in stored procedure.
DECLARE #RecordSelectionSql VARCHAR(MAX)
SET #RecordSelectionSql = (SELECT SQLQUERY FROM RecordSelection WHERE Id = #Id) + ' AND ([Active] = 1)'
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += ',' + CHAR(13) + CHAR(10) + CHAR(9) + name + ' ' + system_type_name
FROM sys.dm_exec_describe_first_result_set(#RecordSelectionSql, NULL, 0);
SELECT #sql = N'CREATE TABLE #TmpImport
(' + STUFF(#sql, 1, 1, N'') + '
);';
EXEC (#sql)
INSERT INTO #TmpImport
EXEC (#RecordSelectionSql)
However I am getting error
Invalid object name '#TmpImport'.
How to properly code this part?
EDIT: added missing condition on RecordSelection
EDIT2:
I cannot use code below because #TmpImport destroyed after #RecordSelectionSql being executed.
DECLARE #RecordSelectionSql AS VARCHAR(MAX)
SET #RecordSelectionSql = 'SELECT X.* INTO #TmpImport FROM ('
+ (SELECT SQLQUERY FROM RecordSelection WHERE Id = #Id) + ' AND ([Active] = 1) AS X'
EXEC (#RecordSelectionSql)
SELECT * FROM #TmpImport
Gives the same error
Invalid object name '#TmpImport'.
Temporary tables are only available within the session that created them. With Dynamic SQL this means it is not available after the Dynamic SQL has run. Your options here are to:
Create a global temporary table, that will persist outside your session until it is explicitly dropped or cleared out of TempDB another way, using a double hash: create table ##GlobalTemp
--To incorporate Radu's very relevant comment below: Because this table persists outside your session, you need to make sure you don't create two of them or have two different processes trying to process data within it. You need to have a way of uniquely identifying the global temp table you want to be dealing with.
You can create a regular table and remember to drop it again afterwards.
Include whatever logic that needs to reference the temp table within the Dynamic SQL script
For your particular instance though, you are best off simply executing a select into which will generate your table structure from the data that is selected.
It's much easier to select into your temp table.
For example
SELECT * INTO #TmpImport FROM SomeTable
I need to update a value in several tables, when migrating a production database to a test environment. The name of the tables can be found in another table. How can I do this?
I mean:
for each value$ in select replace(tablename,' ','') from table1
update value$ set replace(column1,'A','B')
It looks like a nested SQL statement.
You need to build some dynamic sql for this. I prefer to build it in one go and execute as a whole:
declare #sql varchar(max) = ''
select #sql += '
update ' + QUOTENAME(replace(tablename,' ','')) + '
set column1 = replace(column1,''A'',''B'')'
from table1
exec (#sql)
So far in the website I have only found stored procedures to list all the tables in a database, but what I really want to know is how to create a stored procedure in SQL Server to display all data of all tables in a specific database.
I don't want to join the tables and then display a huge table, I want to create some kind of loop that takes the first table of the database, performs a
SELECT * FROM <Table>
query, and then continues with the next table of the database and so on until all tables are displayed.
I know it should be easy but I have never created a stored procedure before so I don't know how to use the variables or go through the tables.
Thank you
Something like this should work:
CREATE Procedure [dbo].[procSelectAllFromAllTables]
AS
DECLARE #table nvarchar(500)
DECLARE #sql nvarchar(520)
DECLARE CursorSelect CURSOR FOR
select table_name from INFORMATION_SCHEMA.tables where table_name not like 'sys%'
OPEN CursorSelect
FETCH NEXT FROM CursorSelect
INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'select * from ' + #table
exec(#sql)
FETCH NEXT FROM CursorSelect
INTO #table
END
CLOSE CursorSelect
DEALLOCATE CursorSelect
RETURN
learn how to create a stored procedure
learn how to use variables in a stored procedure
Get a list of all the table names
use a cursor to create a while loop on a list of all table names
use dynamic sql on 'select * from ' + #tablename
As others have said, this is a silly idea from a practical standpoint, but as an academic exercise, it is fairly simple if you use a bit of dynamic sql and COALESCE(). No cursors or loops required.
DECLARE #SQL VARCHAR(MAX)
SELECT #SQL = COALESCE(#SQL, '') + ' SELECT * FROM ' + s.name + '.' + t.name
FROM sys.tables t INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
EXEC #SQL
In a table there are like 113 columns. and there are two default records in the table, one is for unknown and another is for inapplicable. So, each column has its own default value to represent unknown and inapplicable.
I dont wanna write regular insert statement to get those two records.
so, I tried to insert each column using a cursor.
Got the names of columns for that table from information_schema.columns and tried to insert values from exact table in another location using "insert into select" statement, but the name of the columns that we get from information_schema
Declare #col_name varchar(50)
declare my_cur CURSOR for
select column_name from information_schema.columns
where table_name = 'tabl' and table_catalog = 'db'
and table_schema = 'dbo'
Fetch next from my_cur
into #col_name
while ##FETCH_STATUS = 0
BEGIN
Insert into db.dbo.tabl (***#col_name***)
select ***#col_name*** from openrowset('sqlncli', 'server=my_server; trusted_connection=yes;', db.dbo.tabl)
fetch next from my_cur into #col_name
end
close my_cur
deallocate my_cur
go
But, I did not realize that #col_name would be treated as string, rather than object (column)
Is there any work around for this case or any alternative solution.
I think that getting these defaults populated is the least of your problems.
I'd suggest taking a look at this: Fundamentals of Relational Database Design
And if you still want to do this, it might be better to retrieve all the defaults from the linked server, place them in a temp table, and then join to information_schema.columns to populate your table. You'll probably need to transpose the data to make it work.
You will have to generate the INSERT statement as dynamic SQL and then execute it
Declare #InsertStatement VarChar (Max)
SET #InsertStatement = ''
SET #InsertStatement = #InsertStatement + ' Insert into db.dbo.tabl (' + #col_name + ') '
SET #InsertStatement = #InsertStatement + ' select ' + #col_name + ' from openrowset(''sqlncli'', ''server=my_server''; '
Exec Sp_SQLExec #InsertStatement