在 sql-server 中创建一个允许输入新记录的视图

Posted

技术标签:

【中文标题】在 sql-server 中创建一个允许输入新记录的视图【英文标题】:creating a view in sql-server that allows the entry of new records 【发布时间】:2015-07-31 12:52:56 【问题描述】:

我在 sql server 2012 中有一个名为 AccntTemp 的表,它有一堆列和一个 ID 列。必须在此表中输入数据的人应该看不到 ID 列和其他一些列,但需要能够输入数据。

所以,我需要创建一个允许输入新记录的视图,但只显示我希望她看到的字段。我知道如何创建视图,所以它只显示我希望她看到的字段,但我不知道如何制作视图以便允许输入新记录。

我必须对我的查询进行哪些更改才能使其正常工作?

CREATE VIEW dbo.DataEntry
AS
SELECT code, invno, ven, invdate, amon, accno, amnt, jno, saccno, ckno 
   FROM accnttemp

这只是创建了视图,但是当我转到视图时,我无法修改任何记录或添加任何新记录。我该如何做到这一点?

【问题讨论】:

您的观点是正确的,如果您想从 select 语句中删除列删除,请不要更改 不,我不想删除任何列。我想添加行 你试过了吗? google.com/… 所有其他列(未包含在视图中)是否都可以为空和/或是否有默认值?如果不是,您期望在这些列中放置什么值? “当我转到无法修改的视图时”到底是什么意思?您如何尝试更新视图?更新语句应该可以正常工作。如果您在 SSMS 中浏览视图,那就另当别论了。 【参考方案1】:

如果您的视图由于某种原因(最简单的视图应该是)还不能更新,那么您必须实现手动操作基表的触发器。

例如

CREATE TRIGGER T_DataEntry_I on dbo.DataEntry
instead of insert
as
insert into accnttemp(code, invno, ven, invdate, amon, accno, amnt, jno, saccno, ckno)
SELECT code, invno, ven, invdate, amon, accno, amnt, jno, saccno, ckno 
   FROM inserted

需要进行任何更改以使插入成功。

视图不允许INSERTs 的一个常见原因是,如果基表中有其他列,NULL 和默认值都不起作用。在这种情况下,您必须将这些列添加到上述触发代码中并为它们选择或计算适当的值。


如果不清楚,我不同意 TTeeple 的回答。 SQL 的设计是尽可能地使视图和表无法区分。您应该能够用视图替换表(具有相同的列定义,并将数据保存在适当的其他表中),而不必对使用它的任何客户端应用程序进行任何更改。


事实上,原来的Codd's Rules for Relational Databases 之一是视图应该是可更新的:

规则 6:视图更新规则:

理论上可更新的所有视图都必须可由系统更新。

不幸的是,后来发现对于某些视图,虽然人类可以为它们实现更新,但系统无法找到这样做的方法。

【讨论】:

我认为那时应该有更好的文献。 MSDN 在可更新视图上有very little,我能找到的最多的是someone's post,上面有一个很好的总结(在放大镜下方,从“通过视图修改数据时”开始)。你能指点我一个更好的地方,这样我以后就不会误会了吗? @TTeeple - avi 已经链接到 technet,但同样在 MSDN 上为CREATE VIEW "你可以通过视图修改底层基表的数据,只要满足以下条件...”它还支持 CHECK OPTION 功能,类似于 a_horse_with_no_name 在您的答案下方评论的内容。整个功能只有在您使用可更新视图时才有意义。 所以当我运行这个创建触发器的脚本时,输入数据的人会怎么看? @Damien_The_Unbeliever【参考方案2】:

文档中有一些内容。检查这个link

可更新的视图

您可以通过视图修改基础基表的数据,如 只要满足以下条件:

任何修改,包括 UPDATE、INSERT 和 DELETE 语句, 必须仅引用一个基表中的列。

视图中被修改的列必须直接引用 表列中的基础数据。列不能派生于 任何其他方式,例如通过以下方式:

聚合函数:AVG、COUNT、SUM、MIN、MAX、GROUPING、STDEV、 STDEVP、VAR 和 VARP。

计算。该列不能从一个表达式计算 使用其他列。使用集合运算符形成的列 UNION、UNION ALL、CROSSJOIN、EXCEPT 和 INTERSECT 相当于 计算,也不能更新。

正在修改的列不受 GROUP BY、HAVING 或 DISTINCT 子句。

在视图的 select_statement 中的任何地方都没有使用 TOP 与 WITH CHECK OPTION 子句一起使用。

【讨论】:

是的,我的视图符合该标准,但在视图中我仍然无法更新 在您的查询中,您是否只引用一个基表中的列? 我的查询不用于向表中添加数据。所有这些都是通过表格视图完成的【参考方案3】:

视图不应该允许插入数据,只能读取。您想要做的事情可以通过触发器来实现,但这是不可取的。

您正在寻找一个函数或存储过程。

更新答案,以免我向 cmets 发送垃圾邮件:

这就是为什么你给他们一个接受参数的存储过程。他们对底层逻辑一无所知,他们只知道这个存储过程将他们提供的参数放入他们需要的表中。他们检查视图,他们的新数据现在就在那里。

这通常是不好的做法,因为您只能通过使用触发器来完成它,这可能会产生一些令人讨厌的副作用。因此,如果做得正确并且一切都得到了考虑(现在和未来),那么就继续吧。无论如何,用户必须对基表拥有INSERT, UPDATE, DELETE 权限。

【讨论】:

如何向视图添加触发器?我的上级坚持认为数据输入是通过视图完成的 您可以阅读them here,但我没有这样做的任何经验,因为这是不好的做法。我会回去找你的上级,质疑他为什么认为需要这样做。 默认情况下,简单视图是可更新的,无需触发器。并且用户不需要对基表的权限。 为什么视图不允许插入?这是特定于 SQL Server 的东西吗?一些限制?在 Oracle 和 Postgres 中,允许通过视图插入并不罕见(因为人们也只能通过视图访问数据)。 Postgres 甚至支持with check 选项以防止添加视图不会返回的行。 @a_horse_with_no_name - SQL Server 也有 CHECK OPTION 用于相同的功能。

以上是关于在 sql-server 中创建一个允许输入新记录的视图的主要内容,如果未能解决你的问题,请参考以下文章

多值组合框在表单中创建多条记录

Laravel 雄辩:更新父记录并使用一种形式在另一个表中创建新记录

如何在 HTML/Javascript 中创建可编辑的组合框?

如何在HTML / Javascript中创建可编辑的组合框?

如何在 coredata 中创建数据库视图

在 Access 中创建导航窗口