Je voudrais supprimer un enregistrement spécifique de deux ou plusieurs tables liées entre elles.
Par exemple: j'ai deux tables, les étudiants et les gagnants. Je voudrais supprimer les noms Roy et Peter des deux tables en une seule fois.
tableau: étudiants
> ID name class
> 1 Roy 2
> 2 James 3
> 3 Carl 4
> 4 Peter 4
> 5 Alice 5
tableau: Gagnants
St_ID achievement
1 1
2 1
3 3
4 5
5 5
J'ai plus de 100 tables avec 50 enregistrements spécifiques à supprimer de toutes les tables.
Vous devez y parvenir à l'aide de Dynamic SQL Query
1- Vous devez d'abord lister toutes les tables avec les bases de données correspondantes dans une table temporaire 2- Construire une requête pour les bases de données contenant Students
et Winners
dataTable
Votre script devrait ressembler à
--Get all Databases With corresponding Database
declare @SQL nvarchar(max)
DECLARE @strQuery AS NVARCHAR(MAX)
SET @strQuery = ''
CREATE TABLE #TblTemp (DatabaseName Varchar(255), Tablename Varchar(255))
set @SQL = (select 'union all
select '''+D.name+''' as DatabaseName,
T.name collate database_default as TableName
from '+quotename(D.name)+'.sys.tables as T
'
from sys.databases as D
for xml path(''), type).value('substring((./text())[1], 13)', 'nvarchar(max)')
--print @SQL
INSERT INTO #TblTemp
exec (@SQL)
-- Building Queries
SELECT @strQuery = @strQuery + 'Delete T1 from [' + name + '].dbo.Students As T2
Inner join [' + name + '].dbo.Winners as T1
On T1.[st_ID] = T2.[ID]
Where T1.[name] = IN(''Roy'',''Peter'') ;
DELETE FROM [' + name + '].dbo.Students WHERE [name] = IN(''Roy'',''Peter'') ;
'
from sys.databases
WHERE EXISTS (SELECT 1 FROM #TblTemp WHERE #TblTemp.DatabaseName = name AND #TblTemp.TableName = 'Students') AND
EXISTS (SELECT 1 FROM #TblTemp WHERE #TblTemp.DatabaseName = name AND #TblTemp.TableName = 'Winners')
--VIEW QUERIES (you can copy result and execute it manually)
SELECT @strQuery
--EXECUTE QUERIES
EXEC(@strQuery)
--DROP Temp Table
DROP TABLE #TblTemp
Cela entraînera une requête comme la suivante ( Si ces bases de données contiennent Students
et Winners
Table )
Delete T1 from [master].dbo.Students As T2 Inner join [master].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ;
DELETE FROM [master].dbo.Students WHERE [name] = IN('Roy','Peter') ;
Delete T1 from [tempdb].dbo.Students As T2 Inner join [tempdb].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ;
DELETE FROM [tempdb].dbo.Students WHERE [name] = IN('Roy','Peter') ;
Delete T1 from [model].dbo.Students As T2 Inner join [model].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ;
DELETE FROM [model].dbo.Students WHERE [name] = IN('Roy','Peter') ;
Delete T1 from [msdb].dbo.Students As T2 Inner join [msdb].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ;
DELETE FROM [msdb].dbo.Students WHERE [name] = IN('Roy','Peter') ;
Delete T1 from [AdventureWorks2008R2].dbo.Students As T2 Inner join [AdventureWorks2008R2].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ; DELETE FROM [AdventureWorks2008R2].dbo.Students WHERE [name] = IN('Roy','Peter') ; Delete T1 from [DbMail].dbo.Students As T2 Inner join [DbMail].dbo.Winners as T1 On T1.[st_ID] = T2.[ID] Where T1.[name] = IN('Roy','Peter') ;
Je ne sais pas maintenant si c'est ce que vous demandiez dans votre question ci-dessous (Votre question n'était pas spécifique comme celle-ci, donc ma réponse fournissait la logique SQL dynamique en général)
Je pense que l'approche correcte consiste à supprimer d'abord l'enregistrement de la table Student sans SQL dynamique et à stocker l'ID supprimé dans la table temporaire.
comme ça,
DECLARE @DeletedSTID table(id int not null)
delete from Students
output deleted.id into @DeletedSTID
where name in('Peter','Roy')
select * from @DeletedSTID
Dans l'exemple ci-dessus, je n'ai pas besoin d'utiliser "where name in ()" à chaque fois. Je l'utilise une fois et le stocke dans une table temporaire.
Par exemple, j'utilise Adventure DB,
USE AdventureWorks2012
GO
CREATE TABLE #DeletedSTID (id INT NOT NULL)
CREATE TABLE #temp (tablename VARCHAR(100))
DECLARE @Sql VARCHAR(max) = ''
BEGIN TRY
BEGIN TRANSACTION
DELETE
FROM HumanResources.EmployeeDepartmentHistory
OUTPUT deleted.BusinessEntityID
INTO #DeletedSTID
WHERE BusinessEntityID IN (
1
,2
)
INSERT INTO #temp
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'BusinessEntityID'
AND TABLE_NAME NOT LIKE 'v%'
SELECT *
FROM #DeletedSTID
SELECT *
FROM #temp
SELECT @Sql = @Sql + ' delete from ' + tablename + ' a where exists
(select id from #DeletedSTID b where b.id=a.BusinessEntityID) '
FROM #temp
PRINT @Sql
EXEC (@Sql)
ROLLBACK
--COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH
DROP TABLE #temp
DROP TABLE #DeletedSTID
Vous devrez de toute façon répertorier explicitement les tables que vous devez supprimer.
L'un des scénarios serait de créer une table avec la liste des tables que vous souhaitez supprimer et de parcourir chacune d'elles en appliquant une instruction delete
appropriée basée sur id's
des étudiants avec des noms spécifiques.
Pour parcourir toutes les tables de la base de données, vous pouvez utiliser quelque chose comme ceci:
DECLARE c_tables CURSOR
FOR SELECT table_name
FROM INFORMATION_SCHEMA.TABLES;
DECLARE
@table_name VARCHAR(100);
OPEN c_tables;
FETCH NEXT FROM c_tables INTO
@table_name;
WHILE @@FETCH_STATUS=0
BEGIN
--<your command here>
FETCH NEXT FROM c_tables INTO
@table_name;
END;
CLOSE c_tables;
DEALLOCATE c_tables;
Et n'oubliez pas de tester delete
dans l'environnement de test.