对于我的应用程序中的实体,我打算记录像DateCreated,DateModified,IPAddress等通用元数据。在实体表中添加这些列是否有意义,还是最好有一个表来记录meta-数据中每一行都链接回它对应的项目?稍后为了报告和分析的目的,我可以创建所需的观点。将元数据记录为实体表的一部分还是单独的?
0
A
回答
1
我使用了一个特殊的查询,将所有这些常用列(我称之为审计列)添加到所有表(使用光标越过信息模式),这使得它可以很容易地将它们应用到新的数据库。
我的列(特定的SQL Server):
RowId UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()), Created DATETIME NOT NULL DEFAULT (GETDATE()), Creator NVARCHAR(256) NOT NULL DEFAULT(SUSER_SNAME()) RowStamp TIMESTAMP NOT NULL
现在,在一个完全规范化模式,我只需要RowId
,这将链接到含有其他行的审核表。事实上,经过反思,我几乎希望我走下了这条路 - 主要是因为它使表格变得丑陋(实际上我把这些列从数据库模式图中排除)。
但是,当处理非常大的数据集时,您可以通过在表中使用这些数据来提高性能,并且迄今为止我还没有遇到过这个系统的任何问题。
编辑:不妨张贴代码添加审计列:
DECLARE AuditCursor CURSOR FOR SELECT TABLE_SCHEMA, TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0 AND TABLE_NAME NOT IN ('sysdiagrams') AND TABLE_NAME NOT LIKE 'dt_%' -- NB: you could change the above to only do it for certain tables OPEN AuditCursor DECLARE @schema varchar(128), @table varchar(128) FETCH NEXT FROM AuditCursor INTO @schema, @table WHILE @@FETCH_STATUS -1 BEGIN PRINT '* Adding audit columns to [' + @schema + '].[' + @table + ']...' IF NOT EXISTS (SELECT NULL FROM information_schema.columns WHERE table_schema = @schema AND table_name = @table AND column_name = 'Created') BEGIN DECLARE @sql_created varchar(max) SELECT @sql_created = 'ALTER TABLE [' + @schema + '].[' + @table + '] ADD [Created] DATETIME NOT NULL CONSTRAINT [DF_' + @table + '_Created] DEFAULT (GETDATE())' EXEC (@sql_created) PRINT ' - Added Created' END ELSE PRINT ' - Created already exists, skipping' IF NOT EXISTS (SELECT NULL FROM information_schema.columns WHERE table_schema = @schema AND table_name = @table AND column_name = 'Creator') BEGIN DECLARE @sql_creator varchar(max) SELECT @sql_creator = 'ALTER TABLE [' + @schema + '].[' + @table + '] ADD [Creator] VARCHAR(256) NOT NULL CONSTRAINT [DF_' + @table + '_Creator] DEFAULT (SUSER_SNAME())' EXEC (@sql_creator) PRINT ' - Added Creator' END ELSE PRINT ' - Creator already exists, skipping' IF NOT EXISTS (SELECT NULL FROM information_schema.columns WHERE table_schema = @schema AND table_name = @table AND column_name = 'RowId') BEGIN DECLARE @sql_rowid varchar(max) SELECT @sql_rowid = 'ALTER TABLE [' + @schema + '].[' + @table + '] ADD [RowId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [DF_' + @table + '_RowId] DEFAULT (NEWID())' EXEC (@sql_rowid) PRINT ' - Added RowId' END ELSE PRINT ' - RowId already exists, skipping' IF NOT EXISTS (SELECT NULL FROM information_schema.columns WHERE table_schema = @schema AND table_name = @table AND (column_name = 'RowStamp' OR data_type = 'timestamp')) BEGIN DECLARE @sql_rowstamp varchar(max) SELECT @sql_rowstamp = 'ALTER TABLE [' + @schema + '].[' + @table + '] ADD [RowStamp] ROWVERSION NOT NULL' EXEC (@sql_rowstamp) PRINT ' - Added RowStamp' END ELSE PRINT ' - RowStamp or another timestamp already exists, skipping' -- basic tamper protection against non-SA users PRINT ' - setting DENY permission on audit columns' DECLARE @sql_deny VARCHAR(1000) SELECT @sql_deny = 'DENY UPDATE ON [' + @schema + '].[' + @table + '] ([Created]) TO [public]' + 'DENY UPDATE ON [' + @schema + '].[' + @table + '] ([RowId]) TO [public]' + 'DENY UPDATE ON [' + @schema + '].[' + @table + '] ([Creator]) TO [public]' EXEC (@sql_deny) PRINT '* Completed processing [' + @schema + '].[' + @table + ']' FETCH NEXT FROM AuditCursor INTO @schema, @table END CLOSE AuditCursor DEALLOCATE AuditCursor GO
1
如果您只想保留最新信息(如最后一次修改时间和IP地址),请将其放在表格中。如果你想要更像审计日志的东西,在那里你可以看到所有的历史变化,那么它应该在一个单独的表格中。
0
这是一个关于是否应该规范化数据库的经典问题。我会说,你应该正常化,并且只有在你需要时才会去规范化(性能等)。
相关问题
- 1. 是否将数据拆分为单独的PostgreSQL表
- 2. 新核心数据实体与现有的实体相同:单独的实体还是其他解决方案?
- 3. MySQL数据库设计,两种类型的记录 - 使用一个表还是两个单独的表?
- 4. 将数据框分为单独的列
- 5. 在同一记录中将分隔的字段拆分为单独的列
- 6. 作为ETL的一部分还是数据库内的聚合?
- 7. 实体数据源的记录数
- 8. 分组在一个单独的记录多个记录
- 9. 如何将单元格值的一部分转换为粗体
- 10. 具有活动记录的实体是对象还是组件?
- 11. 作为sql记录一部分的坐标的数据类型
- 12. 将分隔记录转换为单独的字符串?
- 13. Zend Framework是独立的还是PHP环境的一部分?
- 14. 根据列表的值将记录划分为单个记录,Scala
- 15. SQL查询查找表记录是同一表的一部分
- 16. 成员表和其他表在一个数据库中还是单独的?
- 17. 是否可以编辑表单并将其保存为新记录,同时还可以将旧条目保存为MS Access中的单独记录?
- 18. C# - 使用部分类还是单独的?
- 19. 如何将单独的记录合并为一个?
- 20. 实体框架 - 为每个表单独模型是必要的?
- 21. 将数组的单独元素划分为单独的文本字段(PHP)
- 22. ios核心数据 - 将实体记录复制到另一实体
- 23. 如何将手写文本表单分割为单独的部分和单词?
- 24. 在Libreoffice Calc Basic中将单元格文本的部分标记为粗体?
- 25. 将数据从一个单元拆分为多个单元
- 26. 如何将活动记录重新分配给CRM 2011中另一实体中的其他实体记录?
- 27. 将日期的一部分作为单独变量获取
- 28. VB - 串行数据分割串并单独记录到Excel
- 29. Rails - 复制表单的一部分以提交多个记录
- 30. 如何将两个单独的数据添加到一条记录中?