DELETE (Transact-SQL)

Применимо к:SQL ServerБаза данных SQL AzureУправляемый экземпляр SQL AzureAzure Synapse AnalyticsСистема платформы аналитики (PDW)Хранилище в Microsoft FabricБаза данных SQL в Microsoft Fabric

Удаляет одну или несколько строк из таблицы или представления в SQL Server.

Соглашения о синтаксисе Transact-SQL

Syntax

-- Syntax for SQL Server and Azure SQL Database  
  
[ WITH <common_table_expression> [ ,...n ] ]  
DELETE   
    [ TOP ( expression ) [ PERCENT ] ]   
    [ FROM ]   
    { { table_alias  
      | <object>   
      | rowset_function_limited   
      [ WITH ( table_hint_limited [ ...n ] ) ] }   
      | @table_variable  
    }  
    [ <OUTPUT Clause> ]  
    [ FROM table_source [ ,...n ] ]   
    [ WHERE { <search_condition>   
            | { [ CURRENT OF   
                   { { [ GLOBAL ] cursor_name }   
                       | cursor_variable_name   
                   }   
                ]  
              }  
            }   
    ]   
    [ OPTION ( <Query Hint> [ ,...n ] ) ]   
[; ]  
  
<object> ::=  
{   
    [ server_name.database_name.schema_name.   
      | database_name. [ schema_name ] .   
      | schema_name.  
    ]  
    table_or_view_name   
}  
-- Syntax for Azure Synapse Analytics and Microsoft Fabric

[ WITH <common_table_expression> [ ,...n ] ] 
DELETE [database_name . [ schema ] . | schema. ] table_name  
FROM [database_name . [ schema ] . | schema. ] table_name 
JOIN {<join_table_source>}[ ,...n ]  
ON <join_condition>
[ WHERE <search_condition> ]   
[ OPTION ( <query_options> [ ,...n ]  ) ]  
[; ]  

<join_table_source> ::=   
{  
    [ database_name . [ schema_name ] . | schema_name . ] table_or_view_name [ AS ] table_or_view_alias 
    [ <tablesample_clause>]  
    | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]  
}  
-- Syntax for Parallel Data Warehouse  
  
DELETE 
    [ FROM [database_name . [ schema ] . | schema. ] table_name ]   
    [ WHERE <search_condition> ]   
    [ OPTION ( <query_options> [ ,...n ]  ) ]  
[; ]  

Arguments

С common_table_expression <>
Задаёт временное названное множество результатов, также известное как выражение DELETE общей таблицы, определённое в рамках этого оператора. Результирующий набор получается из инструкции SELECT.

Общие табличные выражения также могут использоваться с операторами SELECT, INSERT, UPDATE, и CREATE VIEW . Дополнительные сведения см. в статье WITH common_table_expression (Transact-SQL).

TOP (выражение) [ PERCENT ]
Задает количество или процент удаляемых случайных строк. expression может быть либо числом, либо процентом от числа строк. Строки, указанные в выражении TOP, используются с INSERT, UPDATEили DELETE не расположены в каком-либо порядке. Дополнительные сведения см. в разделе TOP (Transact-SQL).

FROM
Необязательное ключевое слово, которое можно использовать между DELETE ключевым словом и целевой table_or_view_name, или rowset_function_limited.

table_alias
Псевдоним, заданный в предложении FROM table_source и представляющий таблицу или представление, строки которых будут удалены.

server_name
Применимо: SQL Server 2008 (10.0.x) и более поздних версий.

Имя сервера (с использованием имени связанного сервера или функции OPENDATASOURCE в качестве имени сервера), на котором расположена таблица или представление. Если указано server_name, необходимо указать database_name и schema_name.

database_name
Имя базы данных.

schema_name
Имя схемы, которой принадлежит таблица или представление.

table_or_view_name
Имя таблицы или представления, откуда удаляются строки.

Переменная таблицы в рамках своей области также может использоваться как источник таблицы в DELETE операторе.

Представление, на которое ссылается аргумент table_or_view_name, должно быть обновляемым и ссылаться только на одну базовую таблицу в предложении FROM определения представления. Для получения дополнительной информации об обновляемых видах см. CREATE VIEW (Transact-SQL).

rowset_function_limited
Применимо: SQL Server 2008 (10.0.x) и более поздних версий.

Функция OPENQUERY или OPENROWSET в зависимости от возможностей поставщика.

С (<table_hint_limited> [... n] )
Задает одно или несколько табличных указаний, разрешенных для целевой таблицы. Ключевое слово WITH и круглые скобки обязательны. Использование ключевых слов NOLOCK и READUNCOMMITTED запрещено. Дополнительные сведения об указаниях по таблицам см. в разделе Указания по таблицам (Transact-SQL).

<OUTPUT_Clause>
Возвращает удалённые строки или выражения, основанные на них, в рамках DELETE операции. Предложение OUTPUT не поддерживается ни в каких инструкциях DML, направленных на представления и удаленные таблицы. Дополнительные сведения об аргументах и логике работы этого предложения см. в разделе Предложение OUTPUT (Transact-SQL).

От table_source
Задает дополнительное предложение FROM. Это Transact-SQL расширение, позволяющее DELETE указывать данные из <table_source> и удалять соответствующие строки из таблицы в первом предложении FROM.

Это расширение, в котором задается соединение, может быть использовано вместо вложенного запроса в предложении WHERE для указания удаляемых строк.

Дополнительные сведения см. в разделе FROM (Transact-SQL).

WHERE
Указывает условия, используемые для ограничения числа удаляемых строк. Если предложение WHERE не предоставлено, DELETE удаляется все строки из таблицы.

Предусмотрено два вида операций удаления в соответствии с тем, что указывается в предложении WHERE.

  • Операции удаления с поиском указывают условие поиска для уточнения строк, которые будут удалены. Например, WHERE column_name = value.

  • Операции удаления по позиции используют предложение CURRENT OF для указания курсора. Удаление осуществляется в текущей позиции курсора. Это может быть точнее, чем поисковое DELETE утверждение, использующее оговорку WHERE search_condition для удаления строк. Поисковая DELETE оператор удаляет несколько строк, если условие поиска не идентифицирует одну строку уникально.

<search_condition>
Указывает ограничивающие условия для удаляемых строк. Количество предикатов, которое может содержать условие поиска, не ограничено. Дополнительные сведения см. в разделе Условие поиска (Transact-SQL).

ТЕКУЩЕЕ
Задаёт, что выполняется DELETE в текущем положении указанного курсора.

GLOBAL
Указывает, что аргумент cursor_name ссылается на глобальный курсор.

cursor_name
Имя открытого курсора, из которого производится выборка. Если существует как глобальный, так и локальный курсор с именем cursor_name, этот аргумент ссылается на глобальный курсор, если указан аргумент GLOBAL, в противном случае он ссылается на локальный курсор. Курсор должен позволять производить обновления.

cursor_variable_name
Имя переменной курсора. Переменная курсора должна содержать ссылку на курсор, обновления которого разрешены.

ВАРИАНТ (<query_hint> [ ,... n] )
Ключевые слова, которые указывают, какие указания оптимизатора применяются при настройке способа обработки инструкции ядром СУБД. Дополнительные сведения см. в разделе Указания запросов (Transact-SQL).

Лучшие практики

Для удаления всех строк в таблице воспользуйтесь TRUNCATE TABLE. TRUNCATE TABLE быстрее и DELETE использует меньше ресурсов системного и транзакционного журнала. TRUNCATE TABLE имеет ограничения, например, таблица не может участвовать в репликации. Дополнительные сведения см. в разделе TRUNCATE TABLE (Transact-SQL)

Для возврата в клиентское приложение количества удаленных строк используйте функцию @@ROWCOUNT. Для получения дополнительной информации смотрите @@ROWCOUNT (Transact-SQL).

Обработка ошибок

Вы можете реализовать обработку ошибок для DELETE оператора, указав его в конструкции TRY...CATCH .

При выполнении инструкции DELETE может возникнуть ошибка, если инструкция нарушает триггер или пытается удалить строку, на которую ссылаются данные в другой таблице с помощью ограничения FOREIGN KEY. Если DELETE удаляет несколько строк, и одна из удаленных строк нарушает триггер или ограничение, эта инструкция отменяется, возвращается ошибка и строки не удаляются.

Когда DELETE оператор сталкивается с арифметической ошибкой (переполнением, делением на 0 или ошибкой домена), возникшей при вычислении выражения, ядро СУБД обрабатывает эти ошибки так, будто SET ARITHABORT они включёны. Оставшаяся часть пакетной операции отменяется и возвращается сообщение об ошибке.

Interoperability

DELETE может использоваться в теле пользовательской функции, если изменённый объект является переменной таблицы.

При удалении строки, содержащей столбец FILESTREAM, также удаляются и связанные с ней файлы файловой системы. Базовые файлы удаляются сборщиком мусора FILESTREAM. Дополнительные сведения см. в разделе Доступ к данным FILESTREAM с помощью Transact-SQL.

Клауза FROM не может быть указана в DELETE операторе, который ссылается прямо или косвенно на представление с определённым INSTEAD OF триггером. Для получения дополнительной информации о триггерах ВМЕСТО ОФ см. CREATE TRIGGER (Transact-SQL).

В настоящее время пункт FROM не может быть указан в DELETE заявлении на Warehouse в Microsoft Fabric.

Ограничения

При использовании TOP с DELETE строки, на которые имеются ссылки, не упорядочиваются, а предложение ORDER BY не может быть прямо указано в этой инструкции. Если вам нужно использовать TOP для удаления строк в значимом хронологическом порядке, вы должны использовать TOP вместе с предложением ORDER BY в инструкции подзапроса. См. подраздел «Примеры» далее в этом разделе.

TOP нельзя использовать вместе с инструкцией DELETE для секционированных представлений.

Поведение блокировки

По умолчанию оператор DELETE всегда получает монопольную блокировку намерения (IX) для объекта таблицы и страницы, которая изменяет, монопольная блокировка (X) на строках, которые она изменяет, и удерживает эти блокировки до завершения транзакции.

При монопольной блокировке намерения (IX) другие транзакции не могут изменять тот же набор данных; Операции чтения могут выполняться только с использованием указания NOLOCK или считывания неуправляемого уровня изоляции. Вы можете задать подсказки для отмены этого поведения по умолчанию на время DELETE действия оператора, указав другой метод блокировки, однако мы рекомендуем использовать подсказки только в крайнем случае опытными разработчиками и администраторами баз данных. Дополнительные сведения см. в статье Указания по таблицам (Transact-SQL).

Если строки удаляются из кучи, ядро СУБД может использовать блокировку строки или страницы для операции. В результате пустые страницы, в которых выполняются операции удаления, остаются размещенными для кучи. Если их не освободить, занимаемое ими место не может быть использовано под другие объекты базы данных.

Чтобы удалить из кучи строки и освободить страницы, воспользуйтесь одним из следующих методов.

  • Укажите указание TABLOCK в инструкции DELETE. Использование указания TABLOCK приводит к тому, что операция удаления принимает блокировку IX для объекта вместо строки или блокировки страницы. что позволит освободить страницы. Дополнительные сведения о подсказке TABLOCK см. в табличных подсказках (Transact-SQL).

  • Если из таблицы удаляются все строки, пользуйтесь инструкцией TRUNCATE TABLE.

  • Перед удалением строк создайте в куче кластеризованный индекс. Потом его можно будет удалить. Этот метод потребует больше времени и потребляет больше временных ресурсов.

Note

Пустые страницы можно удалить из кучи в любое время с помощью инструкции ALTER TABLE <table_name> REBUILD.

Если включена оптимизированная блокировка, некоторые аспекты поведения блокировки для DELETE изменения. Например, монопольные блокировки (X) не хранятся до завершения транзакции. Дополнительные сведения см. в оптимизированныхблокировки.

Поведение ведения логов

Заявление DELETE всегда полностью логируется.

Security

Permissions

Разрешения DELETE необходимы для целевой таблицы. Разрешения SELECT также необходимы, если инструкция содержит предложение WHERE.

DELETE По умолчанию права доступны для членов sysadmin роли фиксированного сервера, ролей db_owner базы данных и db_datawriter владельца таблицы. Члены ролей sysadmin, db_owner и db_securityadmin, а также владелец таблицы могут передавать разрешения другим пользователям.

Examples

Category Используемые элементы синтаксиса
Базовый синтаксис DELETE
Ограничение удаляемых строк ОТКУДА * * курсор *
Удаление строк из удаленной таблицы Связанный сервер * функция набора строк OPENQUERY * функция набора строк OPENDATASOURCE
Захват результатов DELETE утверждения Предложение OUTPUT

Базовый синтаксис

Примеры в этом разделе демонстрируют базовую функциональность DELETE оператора с использованием минимально необходимого синтаксиса.

A. Использование DELETE без оговорки WHERE

Следующий пример удаляет все строки из SalesPersonQuotaHistory таблицы базы данных AdventureWorks2025, потому что клауза WHERE не используется для ограничения количества удалённых строк.

DELETE FROM Sales.SalesPersonQuotaHistory;  
GO  

Ограничение удаляемых строк

В примерах в этом разделе описываются способы ограничения количества удаляемых строк.

B. Использование предложения WHERE для удаления набора строк

Следующий пример удаляет все строки из ProductCostHistory таблицы базы данных AdventureWorks2025, в которой значение в столбце StandardCost превышает 1000.00.

DELETE FROM Production.ProductCostHistory  
WHERE StandardCost > 1000.00;  
GO  

В следующем примере показано использование более сложного предложения WHERE. Предложение WHERE определяет два условия, которые должны быть выполнены для определения удаляемых строк. Значение в столбце StandardCost должно быть в диапазоне от 12.00 до 14.00 , а значение в столбце SellEndDate должно быть равно NULL. В примере также отображается значение из функции @@ROWCOUNT для возврата количества удалённых строк.

DELETE Production.ProductCostHistory  
WHERE StandardCost BETWEEN 12.00 AND 14.00  
      AND EndDate IS NULL;  
PRINT 'Number of rows deleted is ' + CAST(@@ROWCOUNT as char(3));  

C. Использование курсора для определения удаляемой строки

Следующий пример удаляет одну строку из EmployeePayHistory таблицы базы данных AdventureWorks2025 с помощью курсора под названием complex_cursor. Операция удаления затрагивает только одну строку, выбранную в данный момент курсором.

DECLARE complex_cursor CURSOR FOR  
    SELECT a.BusinessEntityID  
    FROM HumanResources.EmployeePayHistory AS a  
    WHERE RateChangeDate <>   
         (SELECT MAX(RateChangeDate)  
          FROM HumanResources.EmployeePayHistory AS b  
          WHERE a.BusinessEntityID = b.BusinessEntityID) ;  
OPEN complex_cursor;  
FETCH FROM complex_cursor;  
DELETE FROM HumanResources.EmployeePayHistory  
WHERE CURRENT OF complex_cursor;  
CLOSE complex_cursor;  
DEALLOCATE complex_cursor;  
GO  

D. Использование операторов объединения и вложенных запросов к данным в одной таблице для удаления строк в другой таблице

В следующих примерах показано два способа удаления строк в одной таблице на основании данных в другой таблице. В обоих примерах строки из SalesPersonQuotaHistory таблицы базы данных AdventureWorks2025 удаляются на основе продаж с начала года, хранящихся в SalesPerson таблице. В первой инструкции DELETE показано основанное на вложенных запросах и совместимое с ISO решение, а во второй инструкции DELETE используется оператор FROM языка Transact-SQL для объединения двух таблиц.

-- SQL-2003 Standard subquery  
  
DELETE FROM Sales.SalesPersonQuotaHistory   
WHERE BusinessEntityID IN   
    (SELECT BusinessEntityID   
     FROM Sales.SalesPerson   
     WHERE SalesYTD > 2500000.00);  
GO  
-- Transact-SQL extension  
  
DELETE FROM Sales.SalesPersonQuotaHistory   
FROM Sales.SalesPersonQuotaHistory AS spqh  
INNER JOIN Sales.SalesPerson AS sp  
ON spqh.BusinessEntityID = sp.BusinessEntityID  
WHERE sp.SalesYTD > 2500000.00;  
GO  
-- No need to mention target table more than once.  
  
DELETE spqh  
  FROM  
        Sales.SalesPersonQuotaHistory AS spqh  
    INNER JOIN Sales.SalesPerson AS sp  
        ON spqh.BusinessEntityID = sp.BusinessEntityID  
  WHERE  sp.SalesYTD > 2500000.00;  

E. Ограничение числа удаляемых строк с помощью ключевого слова TOP

Когда TOP (n) используется с DELETE, операция удаления выполняется при случайном выборе из n строк. Следующий пример удаляет 20 случайные строки из PurchaseOrderDetail таблицы базы данных AdventureWorks2025 с сроками подачи до 1 июля 2006 года.

DELETE TOP (20)   
FROM Purchasing.PurchaseOrderDetail  
WHERE DueDate < '20020701';  
GO  

Если необходимо с помощью предложения TOP удалять строки в значимом хронологическом порядке, то вместе с ним в инструкции вложенного запроса выборки следует использовать ORDER BY. Следующий запрос удаляет из таблицы PurchaseOrderDetail 10 строк, имеющих самую раннюю дату. Чтобы гарантировать удаление только 10 строк, столбец, указанный в инструкции подзапроса выборки (PurchaseOrderID) должен являться первичным ключом таблицы. Использование неключевого столбца в инструкции подзапроса выборки может привести к удалению более чем 10 строк, если указанный столбец содержит повторяющиеся значения.

DELETE FROM Purchasing.PurchaseOrderDetail  
WHERE PurchaseOrderDetailID IN  
   (SELECT TOP 10 PurchaseOrderDetailID   
    FROM Purchasing.PurchaseOrderDetail   
    ORDER BY DueDate ASC);  
GO  

Удаление строк из удаленной таблицы

В примерах в этом разделе описаны способы удаления строк из удаленной таблицы с использованием в качестве ссылки на удаленную таблицу связанного сервера или функции, возвращающей набор строк. Удаленная таблица существует на другом сервере или экземпляре SQL Server.

Применимо: SQL Server 2008 (10.0.x) и более поздних версий.

F. Удаление данных из удаленной таблицы с помощью связанного сервера

В следующем примере будет удалена строка из удаленной таблицы. Этот пример начинается с создания ссылки на удаленный источник данных с помощью хранимой процедуры sp_addlinkedserver. Имя связанного сервера, MyLinkServer, затем определяется как часть четырехчастного имени объекта в форме server.catalog.schema.object.

USE master;  
GO  
-- Create a link to the remote data source.   
-- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.  
  
EXEC sp_addlinkedserver @server = N'MyLinkServer',  
    @srvproduct = N' ',  
    @provider = N'SQLNCLI',   
    @datasrc = N'server_name',  
    @catalog = N'AdventureWorks2022';  
GO  
-- Specify the remote data source using a four-part name   
-- in the form linked_server.catalog.schema.object.  
  
DELETE MyLinkServer.AdventureWorks2022.HumanResources.Department 
WHERE DepartmentID > 16;  
GO  

G. Удаление данных из удаленной таблицы с помощью функции OPENQUERY

В следующем примере выполняется удаление строк из удаленной таблицы с помощью вызова функции OPENQUERY , возвращающей набор строк. В этом примере используется имя связанного сервера, созданного в предыдущем примере.

DELETE OPENQUERY (MyLinkServer, 'SELECT Name, GroupName 
FROM AdventureWorks2022.HumanResources.Department  
WHERE DepartmentID = 18');  
GO  

H. Удаление данных из удаленной таблицы с помощью функции OPENDATASOURCE

В следующем примере выполняется удаление строк из удаленной таблицы с помощью вызова функции OPENDATASOURCE, возвращающей набор строк. Определите допустимое имя сервера для источника данных, используя формат server_name или server_name\instance_name.

DELETE FROM OPENDATASOURCE('SQLNCLI',  
    'Data Source= <server_name>; Integrated Security=SSPI')  
    .AdventureWorks2022.HumanResources.Department   
WHERE DepartmentID = 17;

Захват результатов DELETE утверждения

I. Использование DELETE с клаузой OUTPUT

Следующий пример показывает, как сохранить результаты DELETE оператора в переменную таблицы в базе данных AdventureWorks2025.

DELETE Sales.ShoppingCartItem  
OUTPUT DELETED.*   
WHERE ShoppingCartID = 20621;  
  
--Verify the rows in the table matching the WHERE clause have been deleted.  
SELECT COUNT(*) AS [Rows in Table] 
FROM Sales.ShoppingCartItem 
WHERE ShoppingCartID = 20621;  
GO  

J. Использование OUTPUT с <from_table_name> в DELETE операторе

Следующий пример удаляет строки в ProductProductPhoto таблице базы данных AdventureWorks2025 на основе критериев поиска, определённых в FROM пункте DELETE оператора. Предложение OUTPUT возвращает столбцы из таблицы, в которой проводится удаление, DELETED.ProductID, DELETED.ProductPhotoIDи столбцы из таблицы Product . Оно используется в предложении FROM для указания удаляемых строк.

DECLARE @MyTableVar table (  
    ProductID int NOT NULL,   
    ProductName nvarchar(50)NOT NULL,  
    ProductModelID int NOT NULL,   
    PhotoID int NOT NULL);  
  
DELETE Production.ProductProductPhoto  
OUTPUT DELETED.ProductID,  
       p.Name,  
       p.ProductModelID,  
       DELETED.ProductPhotoID  
    INTO @MyTableVar  
FROM Production.ProductProductPhoto AS ph  
JOIN Production.Product as p   
    ON ph.ProductID = p.ProductID   
    WHERE p.ProductModelID BETWEEN 120 and 130;  
  
--Display the results of the table variable.  
SELECT ProductID, ProductName, ProductModelID, PhotoID   
FROM @MyTableVar  
ORDER BY ProductModelID;  
GO  

Примеры: Azure Synapse Analytics и система платформы аналитики (PDW)

K. Удаление всех строк из таблицы

Следующий пример удаляет все строки из таблицы Table1, поскольку не указано предложение WHERE, ограничивающее количество удаляемых строк.

DELETE FROM Table1;  

L. DELETE набор строк из таблицы

Следующий пример удаляет все строки таблицы Table1, у которых значение в столбце StandardCost больше 1000,00.

DELETE FROM Table1  
WHERE StandardCost > 1000.00;  

M. Использование LABEL с DELETE оператором

В следующем примере используется метка с этим DELETE утверждением.

DELETE FROM Table1  
OPTION ( LABEL = N'label1' );  
  

N. Использование метки и подсказки запроса с DELETE утверждением

В этом запросе показан базовый синтаксис для использования указания соединения запроса с оператором DELETE. Дополнительные сведения об указаниях соединения и использовании предложения OPTION см. в статье Предложение OPTION (Transact-SQL).

-- Uses AdventureWorks  
  
DELETE FROM dbo.FactInternetSales  
WHERE ProductKey IN (   
    SELECT T1.ProductKey FROM dbo.DimProduct T1   
    JOIN dbo.DimProductSubcategory T2  
    ON T1.ProductSubcategoryKey = T2.ProductSubcategoryKey  
    WHERE T2.EnglishProductSubcategoryName = 'Road Bikes' )  
OPTION ( LABEL = N'CustomJoin', HASH JOIN ) ;  

O. Удаление с помощью предложения WHERE

В этом запросе показано, как удалить с помощью предложения WHERE вместо предложения FROM.

DELETE tableA WHERE EXISTS (
SELECT TOP 1 FROM tableB tb WHERE tb.col1 = tableA.col1
)

P. Удаление по результатам соединения с другой таблицей

В этом примере показано, как удалить из таблицы на основе результата объединения с другой таблицей.

CREATE TABLE dbo.Table1   
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  

CREATE TABLE dbo.Table2   
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);  
GO  
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0);  
INSERT INTO dbo.Table2 VALUES(1, 0.0);  
GO  

DELETE dbo.Table2   
FROM dbo.Table2   
    INNER JOIN dbo.Table1   
    ON (dbo.Table2.ColA = dbo.Table1.ColA)
    WHERE dbo.Table2.ColA = 1;  

См. также

CREATE TRIGGER (Transact-SQL)
INSERT (Transact-SQL)
SELECT (Transact-SQL)
TRUNCATE TABLE (Transact-SQL)
UPDATE (Transact-SQL)
С common_table_expression (Transact-SQL)
@@ROWCOUNT (Transact-SQL)