Удалить из производной таблицы в SQL Server? - PullRequest
0 голосов
/ 22 февраля 2020

Я изучаю запрос в ответе поста Оператор IN в SQL Оператор не работает? , как показано ниже:

DELETE t
    FROM (SELECT t.*,
                 ROW_NUMBER(*) OVER (PARTITION BY P ORDER BY ABS((P & 0xFFFFFFFF) * 256 - F) as seqnum
          FROM MyTable t
         ) t
     WHERE seqnum > 1;

После многих исследований я наконец-то выяснить большинство проблем и пересмотреть запрос следующим образом:

DELETE t2
    FROM (SELECT t.*,
                 ROW_NUMBER() OVER (PARTITION BY P ORDER BY ABS((P & 0xFFFFFFFF) * 256 - F)) as seqnum
          FROM MyTable t
         ) t2
     WHERE seqnum > 1;

Изменения:

  1. Добавить ")" после "F)", так что "ПЕРЕВЕРНИТЕ" (PARTITION BY P ORDER BY ABS ((P & 0xFFFFFFFF) * 256 - F)) "следуйте синтаксису в https://docs.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql?view=sql-server-ver15
  2. Измените ROW_NUMBER (*) на ROW_NUMBER (), так как В приведенном выше документе используйте ROW_NUBMER ().
  3. Измените t во внешнем запросе на t2. Подзапрос в предложении FROM должен иметь псевдоним, поэтому после подзапроса должен быть псевдоним. См. (T- SQL). Почему этот подзапрос требует псевдонима? . Более того, фактический псевдоним во внешнем запросе может совпадать с псевдонимом в подзапросе, см. https://dba.stackexchange.com/questions/16516/subqueries-aliases-same-as-main-queries-aliases, но они относятся к разным объектам. Поэтому я изменяю псевдоним во внешнем запросе с «t» на «t2»

Новичку немного сложно понять многие знания в сложном запросе. Более того, у меня все еще есть две вещи, которые не очень хорошо понимают.

  1. Почему я должен написать «Удалить t2 ОТ» вместо «Удалить ИЗ»? Я нахожу только эту ссылку Разница между DELETE и DELETE FROM в SQL? , но она используется для таблицы JOIN, а не для подзапроса.
  2. Из ссылки на https://dba.stackexchange.com/questions/120233/sql-server-delete-from-subquery-derived-table, я знаю, подзапрос является производной таблицей. Тогда DELETE из t2 просто удаляет записи из таблицы (она является виртуальной), почему он также может выполнять ту же операцию удаления для базовой реальной таблицы MyTable?

Спасибо

Ответы [ 2 ]

3 голосов
/ 22 февраля 2020

"Почему я должен написать" Удалить t2 FROM "вместо" Удалить FROM "?

Самый простой способ - это сначала написать запрос, который делает выбор и затем удалите из него, например, используя CTE:

WITH cte AS (
   SELECT * 
   FROM (
     SELECT t.*,
       ROW_NUMBER() OVER (PARTITION BY P ORDER BY ABS((P & 0xFFFFFFFF) * 256 - F)) as seqnum
     FROM MyTable t) sub
   WHERE seqnum > 1
)
SELECT * FROM cte; -- selecting
--DELETE FROM cte; -- deletion, no where condition, only the ones selected will be removed

Тогда DELETE из t2 просто удаляет записи из таблицы данных (она виртуальная), почему он также может выполнять ту же операцию удаления для базовой реальной таблицы MyTable?

Это похоже на удаление из представления. Строки могут быть удалены из производной таблицы, если выполняются операции SQL ключ сохранения (без агрегации, DISTINCT, отношение n: m).

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

2 голосов
/ 22 февраля 2020

Почему я должен написать "Удалить t2 ОТ" вместо "Удалить ИЗ"?

Это из-за синтаксиса УДАЛИТЬ

DELETE   
    [ FROM ]   <--optional keyword FROM
    { { table_alias  
      | <object>   <--> <object> ::= table_or_view_name
      | @table_variable 
    }
    [ FROM table_source [ ,...n ] ]  <-- note the whole FROM statement is optional, not only the FROM keyword
......

FROM table_source
Specifies an additional FROM clause. **This Transact-SQL extension to DELETE** allows specifying data from <table_source> and deleting the corresponding rows from the table in the first FROM clause.

DELETE (необязательно FROM) и может использовать псевдоним таблицы или объект, который является таблицей или представлением

После DELETE нет производной таблицы / table_source, поэтому (для удаления из производной таблицы) ) единственный применимый вариант - использовать псевдоним. Второй FROM принимает table_source, который может быть производной таблицей. Следовательно, в случае производной таблицы

DELETE [FROM] alias
FROM (....) as alias

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

До тех пор, пока производная Таблица сохраняет детализацию каждой строки (каждая строка может быть идентифицирована отдельно), а область действия dml ограничена одной таблицей (с учетом определения производной таблицы), после чего возможны операции dml с производными таблицами, представлениями, ctes.

...