DELETE (Transact-SQL)

 

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

Область применения: SQL Server (начиная с SQL Server 2008 до текущей версии), База данных SQL Azure.

Значок ссылки на разделCинтаксические обозначения в Transact-SQL

Синтаксис

[ 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 
}

Аргументы

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

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

  • TOP (expression) [ 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 до SQL Server 2014.

    Имя сервера (с использованием имени связанного сервера или функции 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 до SQL Server 2014.

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

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

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

  • FROM 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).

  • CURRENT OF
    Указывает выполнение инструкции DELETE в текущей позиции указанного курсора.

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

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

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

  • OPTION ( <query_hint> [ ,... n] )
    Ключевые слова, показывающие, какие указания оптимизатора применяются при настройке способа обработки инструкции компонентом Компонент Database Engine. Дополнительные сведения см. в разделе Указания запросов (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, компонент Компонент Database Engine будет обрабатывать эти ошибки, как если бы параметр SET ARITHABORT имел значение ON. Оставшаяся часть пакетной операции отменяется и возвращается сообщение об ошибке.

Совместимость

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

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

Предложение FROM нельзя указывать в инструкции DELETE, ссылающейся (прямо или косвенно) на представление, в котором указан триггер INSTEAD OF. Дополнительные сведения о триггерах INSTEAD OF см. в разделе CREATE TRIGGER (Transact-SQL).

Ограничения

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

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

Режим блокировки

По умолчанию инструкция DELETE всегда получает монопольную блокировку (X) на таблицу, которую она изменяет, и держит блокировку до тех пор, пока транзакция не завершится. Если ресурс удерживается монопольной (X) блокировкой, то другие транзакции не могут изменять данные. Операции считывания будут допускаться только при наличии подсказки NOLOCK или уровня изоляции незафиксированной операции чтения. Можно переопределить поведение оптимизатора запросов по умолчанию с помощью табличных подсказок на время выполнения инструкции DELETE указанием другого способа блокировки, но использовать подсказки рекомендуется только опытным разработчикам и администраторам баз данных и только при крайней необходимости. Дополнительные сведения см. в разделе Табличные указания (Transact-SQL).

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

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

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

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

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

Примечание

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

Режим ведения журнала

Инструкция DELETE всегда полностью регистрируется в журнале.

Безопасность

Разрешения

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

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

Примеры

Категория

Используемые элементы синтаксиса

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

DELETE

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

WHERE • FROM • курсор •

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

Связанный сервер • OPENQUERY, функция набора строк • OPENDATASOURCE, функция набора строк

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

OUTPUT, предложение

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

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

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

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

DELETE FROM Sales.SalesPersonQuotaHistory;
GO

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

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

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

Следующий пример удаляет все строки таблицы ProductCostHistory в базе данных AdventureWorks2012, у которых значение в столбце 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));

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

Следующий пример удаляет одну строку из таблицы EmployeePayHistory в базе данных AdventureWorks2012 с помощью курсора my_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

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

В следующих примерах показано два способа удаления строк в одной таблице на основании данных в другой таблице. В обоих примерах из таблицы SalesPersonQuotaHistory в базе данных AdventureWorks2012 будут удалены строки на основании сведений о продажах за текущий год, хранящихся в таблице 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

-- Mention target table, SalesPersonQuotaHistory, only once. Simpler.

DELETE spqh
  FROM
               Sales.SalesPersonQuotaHistory AS spqh
    INNER JOIN Sales.SalesPerson             AS sp   ON spqh.BusinessEntityID = sp.BusinessEntityID
  WHERE
    sp.SalesYTD > 2500000.00;

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

Если с инструкцией DELETE применяется предложение TOP (n), то операция удаления производится над n случайно выбранных строк. Следующий пример удаляет 20 случайных строк из таблицы PurchaseOrderDetail в базе данных AdventureWorks2012, имеющих дату ранее 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 до SQL Server 2014.

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

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

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'AdventureWorks2012';
GO

-- Specify the remote data source using a four-part name 
-- in the form linked_server.catalog.schema.object.

DELETE MyLinkServer.AdventureWorks2012.HumanResources.Department WHERE DepartmentID > 16;
GO

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

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

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

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

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

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

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

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

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

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

Б. Использование предложения OUTPUT с <from_table_name> в инструкции DELETE

Следующий пример удаляет строки в таблице ProductProductPhoto в базе данных AdventureWorks2012 на основе критерия поиска, указанного в предложении 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

См. также

CREATE TRIGGER (Transact-SQL)
Инструкция INSERT (Transact-SQL)
SELECT (Transact-SQL)
TRUNCATE TABLE (Transact-SQL)
UPDATE (Transact-SQL)
WITH обобщенное_табличное_выражение (Transact-SQL)
@@ROWCOUNT (Transact-SQL)