我不确定是否有比我尝试的更简单、更有效的方法。如果可能的话,我想要一些指导/建议
TLDR;没有
您需要了解视图不是数据库中的数据;它是一个存储的 SQL 查询,每次您从视图中选择时都会运行该查询。
SQL Server 甚至可能会获取您的查询并将其与提供视图的查询混合并优化它们并运行它们,因此它甚至不一定会运行视图查询,获取所有百万条记录视图代表,然后通过它们寻找一个叫做君士坦丁堡 Ernhardt 的人 - SQL Server 可能认为最好静默透明地重写您提供的查询,因此它的计划和运行与您可能的想法完全不同 - 它这样做是为了每个查询都在一个称为优化的过程中。
你的观点是:
CREATE VIEW MyView AS
SELECT * FROM Person p JOIN Address a on p.AddressId = a.Id
你写:
SELECT * FROM MyView WHERE Name = 'Abc' and HouseName = 'def'
您可能认为它会这样做(从概念上讲,您是对的):
SELECT * FROM
(
SELECT * FROM Person p JOIN Address a on p.AddressId = a.Id
) x WHERE Name = 'Abc' and HouseName = 'def'
但它可能会被重写为:
SELECT * FROM Person p JOIN Address a on p.AddressId = a.Id WHERE Name = 'Abc' and HouseName = 'def'
所以现在已经解决了,您可以看到视图只是表顶部的查询,每次您从中选择时都会运行它 - 如何从查询中删除数据?
你不能,因为查询没有数据;他们从表中检索数据
“从视图中删除数据”的唯一方法是从视图从中选择数据的表中删除数据
您只能通过相关表上的DELETE 语句来做到这一点
您可以在视图上编写INSTEAD OF 触发器,然后从视图中删除,SQL Server 将运行触发器(从基础表中删除)。看起来您正在从视图中删除数据,但实际上,您只是在使用一种机制从基础表中删除数据,就像视图是将数据从这些表中拖出的机制一样。
您可以编写一个删除数据的存储过程,但同样,这只是从基础表中删除数据的一种机制
根据您的业务目标和以某种方式封装您的软件的愿望,选择您喜欢的任何方法。例如,过去我有一个我无法更改的软件(丢失了源代码或其他),并且它已硬连接到 SELECT FROM users 或 DELETE FROM users - 我们希望该软件能够继续工作,即使用户表被重命名为成员。我们重命名了表,然后创建了一个名为 users 的视图,它刚刚做了 SELECT * FROM members - 允许应用程序继续工作,读取数据。然后,当应用尝试对users 视图(应用仍然认为它是一个表)执行该操作时,我们创建了INSTEAD OF 触发器来更新和删除成员表中的数据
那么为什么这么难呢?好吧,从您的视图中出来的数据甚至可能不再与表格行相关。这是一个简单的版本:
CREATE VIEW MyView AS
SELECT MAX(SUBSTR(Name, 4, 999)) MaxFirstName FROM Person GROUP BY Gender
假设有两个人分别叫Mr Lee Smith和Ms Lee Smith,你已经获取了函数输出的最大值并得到了Lee Smith,现在你想通过分析视图从person表中删除Lee Smith并从 Person 表中删除... 什么?哪个记录?分组将所有记录混合在一起。一个人的最大姓名和另一个人的最小生日..
这是另一个例子,有点可笑但可以想象:
CREATE VIEW MyView AS
SELECT name as x FROM person
UNION
SELECT street FROM address
这很容易产生独特的价值“Penny Lane”——但它是一个人,还是一条路?如果我们从这个视图中删除 x = 'Penny Lane' 应该删除哪个
没有可以运行它的灵丹妙药,它会显示“此表使用这 3 个表”,因此您可以从中删除它们。这甚至都不是一个好的前提。您的视图可能会从一个数据表和一个查找表中进行选择,并且仅仅因为您要从用户表中删除唐纳德特朗普而从查找表中删除性别类型 1,这将是一个错误的选择
如果你想在视图上提供删除功能,你需要编写一些代码;没有一个自动的解决方案可以计算出应该删除哪些表中的哪些数据以及应该保留哪些数据。试想一下,分析一个连接 9 个表、混合连接样式、另外 8 个 VALUES 列表、3 次调用解析一些 json 的交叉应用表值函数、吊起几行生成的视图是多么困难那里有递归 CTE,还有一个枢轴......
绝对没有任何人会编写魔术按钮来将所有内容分开为“计算出基表列表以及应删除哪些数据以满足DELETE FROM MyView WHERE output_of_parsing_function = 'Hello'