Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 日志表中的外键_Sql_Sql Server 2008_Database Design - Fatal编程技术网

Sql 日志表中的外键

Sql 日志表中的外键,sql,sql-server-2008,database-design,Sql,Sql Server 2008,Database Design,嘿,这里有一个设计问题: 我正在从事一个项目,该项目要求我跟踪用户何时执行插入、更新或删除操作。我试图决定的是让Logs表引用受影响行的主键还是其他标识符。为了在使用外键时记录删除,我需要为每个表创建一个已删除列。然而,如果我使用的是没有外键的命名标识符,我最终会在Logs表中遇到名称重复,并且不清楚条目所指的是什么。是否有人对此有实际经验,特别是使用已删除列来维护完整日志对性能的影响 日志表本身的设计中也存在一个相关问题。如果我在单个日志表中使用外键引用,我的第一反应是为每个被监视更改的表创建

嘿,这里有一个设计问题:

我正在从事一个项目,该项目要求我跟踪用户何时执行插入、更新或删除操作。我试图决定的是让Logs表引用受影响行的主键还是其他标识符。为了在使用外键时记录删除,我需要为每个表创建一个已删除列。然而,如果我使用的是没有外键的命名标识符,我最终会在Logs表中遇到名称重复,并且不清楚条目所指的是什么。是否有人对此有实际经验,特别是使用已删除列来维护完整日志对性能的影响

日志表本身的设计中也存在一个相关问题。如果我在单个日志表中使用外键引用,我的第一反应是为每个被监视更改的表创建一个引用列。这对我来说并不理想,好像我必须添加一个新表,然后更改Logs表和任何相关的存储过程。我可以看到的另一种选择是有两列,TableName和RowId。但这将没有固有的外键引用,因为它不知道引用的是什么表


谢谢你的意见

日志表中不需要四列吗<代码>用户标识,
表名
标识
操作

Action
将是“delete”、“update”或“insert”,
Id
将是相关表的主键,其余的都是不言自明的


这样,您就不必有很多列和外键,这只会使插入日志表的速度变慢。无论如何,您都需要使用触发器执行此操作,因此将表名添加到日志表中不会有问题。

假设您跟踪的每个表的日志信息都相同,我将使用一个包含TableID和RowPKValue列的日志表。确实,您不能将RowPKValue移回每个单独的表,但是由于用户(或除您的log SP以外的任何代码)永远不会触及日志表,因此我认为它相当安全

我肯定会使用正在记录的行的PK值,而不是任何其他值(即使您没有引用它的FK),因为PK值就是用于此的

至于删除问题,我认为这取决于1)您希望执行的删除次数和2)您必须将“取消删除”作为应用程序的一部分的可能性

如果删除的次数相对较少,则可以使用“已删除”标志将其保留在表中,然后在指定的时间段结束后将其删除。如果您这样做,我建议使用一种方案,在该方案中,基本表被称为CustomerAll,并且您有一个表视图
CREATE view Customer AS SELECT*FROM CustomerAll,其中Deleted=false
,供前端程序员使用


如果您有大量的删除,我会在删除时将它们移动到第二个表(CustomerDeleted)中,甚至从数据库中移出,这取决于您认为需要再次查找它们的可能性。

首先,取决于行数和索引类型,添加已删除的列可能比删除该行效果更好

其次,我认为最好的选择是将整行存储在日志表中(这将允许记录任何更新)。您还可以使用更规范化的日志表来实现这一点—类似于:

  • 身份证
  • 行动
  • 有效列
  • 旧价值
  • 新价值
这将是一个更多的工作,虽然,你不会得到那么多。我建议您只需将所有数据存储在一个重复的表中,并使用额外的列来显示所采取的操作类型


至于对行的标识符或其他值的引用,无论您如何操作,都会有相同的问题。为了识别影响的行,该行中也必须存在相同的唯一值。一旦该行被删除,唯一值(GUID(t-sql中的uniqueidentifier)也将被删除,顺便说一句,这是一个选项)

您也可以使用2表日志文件设置

LogA-日志id、表名、操作、日期和时间

LogB-日志ID、表ID、列更改、旧值、新值

(编辑到calrify,上面的“table_id”指的是该表中的主键。多个主键可能需要多个字段)

在new_value字段中使用空值表示删除,在旧值中使用空值表示插入

如果您希望避免在每个表上出现“已删除”列,则可以创建一个已删除表来存储已删除的行,并使用视图仅显示活动记录(即在已删除表中没有unqiue键的记录)


有很多有效的方法可以设计这个…

RE:一个日志表而不是影子表

不过,这将是更多的工作,你不会从中得到那么多加布里埃尔·麦克亚当斯

我完全不同意

你的目标是:

跟踪用户何时执行插入、更新或删除

如果每个表都有一个影子表,您如何回答这些问题:

  • 哪些用户昨天做了更改
  • 哪个表更新最多
  • employee=“Page,S”上个月做了什么活动
  • 哪位员工最活跃
  • 你必须仔细检查每一张阴影表才能找到答案。如果您开始记录一个新的表,您必须记住更改这些存储过程以同时访问新的影子表

    如果您有一个其他人建议的日志表,您可以使用