Je souhaite supprimer certaines données de ma table, alors écrivez une requête pour la supprimer. J'ai donc d'abord sélectionné les données que je voulais supprimer à l'aide de cette requête et elle me montre les données correctes
DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
puis j'écris la suppression en utilisant la même condition where mais cela ne fonctionne pas
XXX
ici, je partage quelques captures d'écran pendant que j'exécute la requête
voici quelques exemples de données
c'est le dernier résultat de l'exécution et j'ai attendu 1 minute et le dernier arrêt de l'exécution
Mise à jour le 15-OCT-2019
J'ai essayé le même scénario aujourd'hui, j'en ai importé 5000 enregistrements dans la table et essayez de supprimer ces 5000 enregistrements en utilisant la même requête, et étonnamment, cela fonctionne. J'ai essayé les deux cas
1. les données n'ont pas de clé étrangère, cela fonctionne très bien. Voici la capture d'écran
les deux cas fonctionnent maintenant, je ne sais pas ce qui s'est passé ce jour-là sur le serveur SQL
11 Réponses :
Cela devrait fonctionner correctement, je ne vois rien de mal avec la requête, essayez d'écrire une nouvelle requête dans la nouvelle fenêtre de requête pour vous assurer que la requête est propre
Pour moi, cela fonctionne bien et supprime les données de test de la table p>
DELETE FROM Discipline WHERE Code LIKE '%DHA-DIS%' (2 row(s) affected) select * from Discipline where Code like '%DHA-DIS%'
select * from Discipline select * from Discipline where Code like '%DHA-DIS%'
Vous pouvez voir que la requête ci-dessus fonctionne très bien, elle supprime les 2 lignes qui correspondent à la requête.
Les commentaires ne sont pas destinés à une discussion approfondie; cette conversation a été déplacé pour chatter .
1) Vous avez 5000 lignes à supprimer mais ce n'est pas forcément la table entière. Combien de lignes dans le tableau?
2) Votre instruction LIKE nécessitera une analyse de table pour être satisfaite. S'il y a beaucoup de lignes ou de grandes colonnes, cela prendra beaucoup de temps.
3) Publiez le plan de requête et les statistiques sur les tables qu'il utilise.
4) Si vous annulez une suppression , la base de données sera annulée. C'est pourquoi vous le voyez ne rien faire.
même avec une analyse de table, cela ne devrait pas prendre autant de temps car il n'y a que 5000 lignes dans la table. Je suppose qu'il y a un verrou sur la table par un autre processus
Il est possible qu'il y ait un verrou sur la table Discipline par un autre processus
Vous pouvez trouver les verrous sur votre table en exécutant ce script
declare @lock table (spid int, dbid int, objId int, indId int, Type char(4), resource nchar(32), Mode char(8), status char(6))
declare @who table (spid int, ecid int, status char(30), loginname char(128), hostname char(128), blk char(5), dbname char(128), cmd char(16), request_id INT)
declare @LockSummary table (loginname varchar(28), DB varchar(128), object varchar(30), ToLevel varchar(20), How_Many int, Xclusive_lock_for_command char(16), spid int, hostname char(128))
insert into @lock exec sp_lock
insert into @who exec sp_who
insert into @LockSummary
select loginname,
db_name(dbid) as DB,
object_name(objID) as object,
max(mode) as [ToLevel],
Count(*) as [How Many],
Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command],
l.spid,
hostname
from @lock l
join @who w on l.spid = w.spid
where dbID != db_id('tempdb')
and l.status = 'GRANT'
group by dbID, objID, l.spid, hostname, loginname
select *
from @LockSummary
where object like '%Discipline%'
order by [ToLevel] Desc, [How_Many] Desc, loginname, DB, object
Avez-vous essayé la même requête en mode édition. Vous pouvez le faire
Ctrl + 3 pour modifier la requête. select * from Discipline where Code like '% DHA-DIS%' Si l'exécution prend trop de temps, essayez de changer votre requête en quelque chose comme ça
sélectionnez le top 1000 * de la discipline où le code comme '% DHA-DIS%'
répétez l'étape si cela réussit
Deux choses pourraient ralentir votre suppression
select * from sys.foreign_keys where delete_referential_action > 0
Je vais vérifier cela aussi.
Remarque: Reprenez UP
Si possible Modifiez la discipline PATS en ceci,
DECLARE @TopSize INT = 10000
DECLARE @BatchSize INT = 10000
DECLARE @MaxLimit INT = 1
DECLARE @RowCount INT = 0
BEGIN TRY
WHILE (@TopSize <= @MaxLimit)
BEGIN
delete TOP (@TopSize) from PATS.Discipline
where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
SET @RowCount = @@RowCount
--PRINT @TopSize
IF (
@RowCount = 0
OR @RowCount IS NULL
)
BREAK;
ELSE
SET @TopSize = @TopSize + @BatchSize
END
END TRY
BEGIN CATCH
--catch error
END CATCH
Ou modifiez la colonne possible. p >
CreatedBY peut être converti INT en joignant d'abord manuellement avec la table de préoccupation.
Puis corriger le code.
Je ne parle pas de ce point, Code LIKE '% DHA-DIS%' est NON SARGable .
Ou POURQUOI vous ne devriez pas utiliser.
et si la colonne de code doit être NON Clustered Index ou non.
Modifier la conception de la table vous aidera dans tous les aspects que ce soit la requête Select ou Opération DML et pour toujours.
Vous pouvez également le faire
Placez le Select Resultset dans la table Temp, puis Rejoignez et supprimez
create table #temp (id uniqueidentifier not null primary key) insert into #temp select id from PATS.Discipline where Code like '%DHA-DIS%' delete from PATS.Discipline where exists(select 1 from #temp where #temp.id=PATS.Discipline.id )
Vous pouvez effectuer les deux étapes
Si Supprimer les données est en millions, vous pouvez utiliser la pagination,
ID int PK Code varchar(20) Name varchar(50) CreatedBY varchar(50) or even better INT CreatedDate Datetime2(0) UpdatedBY varchar(50) or even better INT UpdatedDate Datetime2(0)
p >
Cette réponse est basée sur mon expérience personnelle.
Vous stockez uniqueidentifier en tant qu'ID de votre table et en faites une clé de cluster primaire. La suppression d'un tel nombre de lignes prend du temps en raison de la réindexation de votre table. Alors, je suggérerais -
Cela m'a aidé dans un cas similaire. Pourquoi? Parce que dans cette stratégie, l'indexation de cette table n'est manipulée que deux fois. Lors de la suppression, la réindexation de la table ne se produit pas. Pour cette raison, vous constaterez une amélioration significative dans l'exécution de la suppression.
Donc, votre requête devrait être comme ceci-
ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline] GO DELETE FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%' GO ALTER TABLE PATS.Discipline DROP CONSTRAINT [PK_Discipline] PRIMARY KEY CLUSTERED GO
Remarque: Cette stratégie de suppression ne doit être appliquée qu'à ce type de cas où la table a de nombreux index ou la clé primaire est uniqueidentifier et que vous essayez de supprimer plus de lignes de cette table. Mais dans un scénario normal, la même ancienne requête de suppression devrait être appliquée.
Ce n'est probablement pas un problème avec le mot clé LIKE. Le SELECT semble renvoyer beaucoup de lignes correspondantes - je présume relativement rapidement (?) - donc la question est "Qu'est-ce qui est lent (ou qu'est-ce qui empêche) DELETE?" Essayez
DELETE TOP 1 FROM PATS.Discipline WHERE Code LIKE '%DHA-DIS%'
et si cela fonctionne, essayez TOP 10/100 ...
Une supposition éclairée dit que c'est lent à cause de la réindexation et / ou des relations croisées (contraintes de clé étrangère) et / ou simplement la construction d'une transaction très importante.
Comment l'accélérer? Il y a beaucoup de bonnes suggestions parmi les réponses déjà publiées et je suggère également de jeter un œil à ceci: Comment supprimer efficacement des lignes sans utiliser Truncate Table dans un tableau de plus de 500 000 lignes
ça fonctionne comme ça, le problème est qu'il ne supprime pas les données en masse
Avez-vous essayé de supprimer le top 100? Si cela fonctionne, alors la discussion dans le lien que j'ai posté explique pourquoi, pour supprimer le gros, vous devriez le faire en plus petits "morceaux". Il existe des exemples de la manière de procéder proprement. Le DELETE est exécuté de manière transactionnelle, c'est-à-dire que la base de données écrit ses "intentions" (tout ce qu'elle est sur le point de faire) dans le fichier journal des transactions (afin qu'elle puisse annuler si quelque chose ne va pas), avant de s'engager (rend le résultat final). En l'absence d'autres preuves (par exemple de verrouillage), c'est probablement pourquoi votre DELETE s'exécute pendant très longtemps. Google "coût de suppression SQL" pour plus.
De rien. Si vous avez répondu à votre question, veuillez cocher la meilleure. Si ce n'est pas le cas, mais que vous avez trouvé la solution vous-même, veuillez la poster.
Autre tout Je ne vois aucun problème avec le code que vous utilisiez à l'origine, bien que l'utilisation d'une instruction similaire sur une requête de suppression ait un impact sur les performances. Si je sais que je ne supprime que quelques milliers de lignes, j'adopte l'approche CTE et je la rejoins sur la table source:
;With DeleteCTE as
(
select
[ID],
Code
from Discipline
where Code like '%DHA-DIS%'
)
Delete
from Discipline D
Inner Join
DeleteCTE DC
on DC.ID = D.ID
Je pense que vous êtes plus préoccupé par le temps d'exécution ici car cela prend beaucoup de temps, vous avez donc annulé l'exécution. J'ai rencontré le même problème dans le passé, ma solution est de redémarrer SQL Management Studio et d'essayer la même requête, cela fonctionnera bien.
@ganesh, redémarrer le serveur sql n'est pas une bonne solution. Un autre processus est peut-être en cours d'exécution sur le serveur.
Il n'y a aucun problème avec la requête que vous avez utilisée.
Il peut y avoir plusieurs raisons. Le câble réseau a peut-être été déconnecté, la base de données était peut-être hors ligne au milieu de l'exécution, il y a peut-être eu une panne de courant, ou l'accès à la table a été verrouillé à cause d'une autre transaction, etc.
Lorsque votre requête échouait, cela prenait parfois même plus d'une minute, n'est-ce pas? Mais quand cela a réussi, l'exécution a été très rapide. Il doit y avoir eu un autre accès à cette table via le réseau au moment où la requête a échoué.
Lorsque vous traitez avec un grand nombre de données comme 5000, vous pouvez avoir des procédures stockées avec des blocs de transactions ajoutés.
qu'est-ce que cela signifie ne pas fonctionner? est-ce que ça jette une erreur
il ne supprime pas une seule ligne de la table
non, ce n'est pas une erreur.
Vous devez nous donner un exemple reproductible avec lequel travailler ici. Si la première sélection renvoie des enregistrements, la deuxième suppression doit supprimer quelque chose.
Êtes-vous sûr que votre commande connecte la même base de données?
Vérifiez s'il existe des déclencheurs sur la table et ce qu'ils font
@DhanilDinesan dbfiddle.uk/… vérifier ce lien votre requête fonctionne correctement
ok ma table a 7 colonnes. et je veux en supprimer 5002
@ D-Shih oui pareil
faites-vous cela dans SSMS? sinon, montrez-nous tout le code. Y a-t-il des déclencheurs sur la table?
@GuidoG oui j'utilise SSMS
et est-ce que vous nous montrez tout le code?
@GuidoG oui c'est la seule chose que je veux faire. J'essayais une importation Excel dans une table, et maintenant je veux supprimer les données importées.
avez-vous besoin de l'ensemble des 5000 données? c'était juste un texte que j'essayais
Dans votre image, la requête est toujours en cours d'exécution. Ce n'est pas encore fini. Avez-vous des déclencheurs dans votre tableau?
Y a-t-il une chance que deux constantes qui semblent identiques soient vraiment différentes? Essayez
Declare @param varchar (20) = '% DHA-DIS%'; sélectionnez * dans PATS.Discipline où Code comme @param; SUPPRIMER DE PATS.Discipline WHERE Code LIKE @param;la suppression de 5000 lignes ne devrait jamais prendre autant de temps, vous devriez rechercher pourquoi cela prend si longtemps. Peut-être y a-t-il un déclencheur sur cette table? peut-être y a-t-il une configuration de clés étrangères avec
suppression en cascadeactivée?@GuidoG non il n'y a pas de déclencheur
@Serg j'ai essayé mais aucune différence
si vous trouvez qu'il s'agit d'une question pertinente, veuillez voter pour cette question
Publiez une photo pour prouver que votre table n'a aucun déclencheur.
@Han a ajouté s'il vous plaît vérifier
D'accord, je crois qu'il n'y a aucun déclencheur dans votre tableau.
Existe-t-il d'autres applications utilisant ce tableau? Peut-être dans une session de débogage de Visual Studio? Si une autre application utilise cette table, alors je peux avoir un verrou sur la table et dans ce cas, votre instruction de suppression devra attendre que ce verrou soit terminé
«Mais ça ne marche pas» ne nous aidera pas à vous aider. Ne fonctionne pas comment ??? Erreur? Rien de supprimé? Toutes les lignes sont-elles supprimées?
@Eric Le problème était que lorsque j'essayais de supprimer en utilisant
LIKE, cela ne supprime pas une seule ligne. Alors je ne savais pas pourquoi cela se passait comme ça. Mais le jour dernier, j'ai essayé avec les mêmes 5000 enregistrements en utilisant la même requête, cela fonctionnait bien.@Eric quand je l'ai essayé la première fois, cela n'a généré aucune erreur, vous pouvez le voir sur les captures d'écran. Le dernier jour, j'ai mis intentionnellement une clé étrangère pour savoir que l'erreur apparaîtra ou non. Mais cela montre une erreur la dernière fois. Je ne sais pas ce qui s'est passé ce jour-là.