Language agnostic &引用;“差异化”;关系数据库中的对象
我们的win32应用程序从MySQL关系数据库中多个表中的数据组装对象。对于此类对象,数据库中存储了多个修订 当存储某个内容的多个修订版本时,迟早您会问自己是否可以可视化两个修订版本之间的差异:)因此我的问题是:什么是“区分”两个这样的数据库对象的好方法?Language agnostic &引用;“差异化”;关系数据库中的对象,language-agnostic,oop,diff,Language Agnostic,Oop,Diff,我们的win32应用程序从MySQL关系数据库中多个表中的数据组装对象。对于此类对象,数据库中存储了多个修订 当存储某个内容的多个修订版本时,迟早您会问自己是否可以可视化两个修订版本之间的差异:)因此我的问题是:什么是“区分”两个这样的数据库对象的好方法? 您会在数据库级别进行比较吗?(听起来不是个好主意:级别太低,对模式太敏感) 你能比较一下这些物体吗? 您是否会编写一个“手动”比较两个对象的属性和字段的函数 您将如何存储差异?在单独的通用“TDiff”对象中 关于如何在用户界面中可视化这
- 您会在数据库级别进行比较吗?(听起来不是个好主意:级别太低,对模式太敏感)
- 你能比较一下这些物体吗?
- 您是否会编写一个“手动”比较两个对象的属性和字段的函数
- 您将如何存储差异?在单独的通用“TDiff”对象中
- 关于如何在用户界面中可视化这些东西,有什么一般性的建议吗
恩,赏金已经结束了,所以我接受了一个答案。如果有可能从我的代表身上多切几个100分,然后给其他一些答案,我会毫不犹豫地这样做。你们所有人的帮助都很好,我非常感激!~在No 20090519上,我已经研究过MysQL的很多次了。不幸的是,没有任何真正好的解决方案可用 我试过的一个工具是mysqldiff(www.mysqldiff.org)。mysqldiff是一个用PHP编写的工具,能够区分mysql模式。不幸的是,它并没有做一个伟大的工作很多时候 mysqlworkbench,MySQLs自己的sqlide提供了生成alter脚本的选项,我可以想象它是通过在内部执行某种diff操作来实现的 Aqua Data Studio是另一个能够比较模式并输出两者差异的工具。虽然adsdiff相当不错,但它不提供创建alter脚本的工具 若我自己写的话,我想我会编写能够比较两个表结构的代码。这样的代码可以调整为高度敏感(Ig,如果列顺序不同于下一个版本,这是一个差异)或更为中等敏感(例如列顺序不是主要问题,数据类型和长度很重要,索引和约束也很重要) 储藏室,我不确定。我将研究诸如Mercurial之类的版本控制系统如何存储其用于修订的差异信息,并使用该信息来详细说明适合DB的方法
最后,对于视觉输出,我建议您查看Aqua数据Stduio比较功能(您可以使用试用版来测试这一点…)。它的diff输出非常好。这只是一个想法,但是您是否值得将正在比较的两个对象版本转换为某种文本格式,然后使用现有的diff程序(例如
diff
)比较这些文本对象?有很多很好的diff程序可以提供很好的视觉表现,等等
比如说
对象1的文本版本:
first_name: Harry
last_name: Lime
address: Wien
version: 0.1
对象2的文本版本:
first_name: Harry
last_name: Lime
address: Vienna
version: 0.2
差异可能类似于:
3,4c3,4
< address: Wien
< version: 0.1
---
> address: Vienna
> version: 0.2
3,4c3,4
<地址:维也纳
<版本:0.1
---
>地址:维也纳
>版本:0.2
我的应用程序dbscript比较存储过程中的分层数据(数据库模式),当然,存储过程必须将每个对象的每个字段/属性与其对应项进行比较。我猜你不会绕过这一步(除非你有一个通用的对象描述模型)
至于问题的UI部分,请看一看屏幕截图,了解它们之间的区别。我会考虑对象的某种常见文本表示,并让文本与现有的差异化工具(如WinMerge)进行比较
我觉得没有必要自己发明diffing,因为我已经有很多很好的工具可以使用了。在PostgreSQL中,我使用了一个与模式不同的表:
history_columns (
column_id smallint primary key,
column_name text not null,
table_name text not null,
unique (table_name, column_name)
);
create temporary sequence column_id_seq;
insert into history_columns
select nextval('column_id_seq'), column_name, table_name
from information_schema.columns
where
table_name in ('table1','table2','table3')
and table_schema=current_schema() and table_catalog=current_database();
create table history (
column_id smallint not null references history_columns,
id int not null,
change_time timestamp with time zone not null
constraint change_time_full_second -- only one change allowed per second
check (date_trunc('second',change_time)=change_time),
primary key (column_id,id,change_time),
value text
);
在桌子上我用了这样一个触发器:
create or replace function save_history() returns trigger as
$$
if (tg_op = 'DELETE') then
insert into historia values (
find_column_id('id',tg_relname), OLD.id,
date_trunc('second',current_timestamp),
OLD.id );
[for each column_name] {
if (char_length(OLD.column_name)>0) then
insert into history values (
find_column_id(column_name,tg_relname), OLD.id,
OLD.change_time, OLD.column_name
)
}
elsif (tg_op = 'UPDATE') then
[for each column_name] {
if (OLD.column_name is distinct from NEW.column_name) then
insert into history values (
find_column_id(column_name,tg_relname), OLD.id,
OLD.change_time, OLD.column_name
);
end if;
}
end if;
$$ language plpgsql volatile;
create trigger save_history_table1
before update or delete on table1
for each row execute procedure save_history();
以Oracle为例
- 使用dbms_元数据将有序对象导出为文本
- 将有序表数据导出为CSV或查询格式
- 制作大文本文件
- 差异
public class Person
{
public string name;
}
public class PersonComparer
{
public PersonComparer(Person old, Person new)
{
....
}
public bool NameIsDifferent() { return old.Name != new.Name; }
public string NameDifferentText() { return NameIsDifferent() ? "Name changed from " + old.Name + " to " + new.Name : ""; }
}
public class ObjectComparer()
{
public ObjectComparer(object old, object new)
{
...
}
public bool PropertyIsDifferent(string propertyName) { return getObjectProperty(old, propertyName) != getObjectProperty(new, propertyName) };
public string PropertyDifferentText(string propertyName) { return PropertyIsDifferent(propertyName) ? propertyName + " " + changed from " + getObjectProperty(old, propertyName) + " to " + getObjectProperty(new, propertyName): ""; }
}
}