gbradley / dbdiff
SQL数据库表差异比较
Requires
- php: >=7.1.0
Requires (Dev)
- phpunit/dbunit: ^4.0
- phpunit/phpunit: ^7
README
SQL数据库表差异比较。DBDiff 允许您比较任何两个表的内容。
$diff->connect($pdo)
->compare($columns)
->from('products_backup', 'products')
->where('vendor', 'Wayland-Yutani')
->output();
需求
DBDiff 需要 PHP 7.1 或更高版本。
安装
使用 Composer 安装
$ composer require gbradley/dbdiff
用法
注意:除了 "final" 方法(如 output()
、each()
和 count()
)之外,DBDiff 方法都是链式调用的,以便于流畅的接口。
连接到数据库
首先创建一个 DBDiff 实例,并将配置好的 PDO 连接传递给构造函数
$pdo = new PDO(...);
$diff = new DiffFB($pdo);
如果您使用具有依赖注入功能的框架(如 Laravel),则可以通过 connect
方法单独传递 PDO 连接
someMethod(DBDiff $diff) {
$diff->connect(DB::connection()->getPdo());
}
指定要比较的列
接下来,使用 compare()
方法指定要比较的表列数组。
$diff->compare([
'name',
'vendor',
'cost',
'price',
'last_updated'
]);
指定表
使用 from()
方法告诉 DBDiff 您正在访问哪些表
$diff->from('products_backup', 'products');
使用 Git 的术语,第一个参数是 源,第二个参数是 目标。
要指定您的表所在的数据库,请将数据库名称作为第三个参数传递。如果您的表位于不同的数据库中,请将 源 和 目标 数据库分别作为第三个和第四个参数传递。
$diff->from('products', 'products', 'db_backup', 'db');
添加约束
您可能只对表中的部分数据感兴趣。如果是这样,请使用 where()
限制结果仅限于两个表中的条件都为真的行
$diff->where('vendor', 'Wayland-Yutani');
主键
默认情况下,您的表上的主键假定是 id
,但您可以使用 primaryKey()
覆盖此设置
$diff->primaryKey('product_id');
结果
默认情况下,调用 output()
将计算差异并输出结果。差异中的每个结果都显示 ID 以及表中不同的列和值。
要对每个结果执行其他操作,请将接受单个结果的方法传递给 output()
$diff->output(function($result) {
Log::info($result);
});
自定义输出格式
当使用 output()
时,使用 DBDiff\Formatter
类来格式化每个差异的结果。如果需要,您可以子类化 Formatter 并将您的类实例传递给 format()
方法
$diff->format(new MyCustomFormatter);
访问原始数据
当然,您可能希望完全避免格式化并直接访问每个差异的原始数据。为此,请调用 each()
方法,并传递一个接受 ID 和源 & 目标数组的功能
$diff->each(function($id, $source, $destination) {
...
});
对于每个计算出的差异,此函数将接收来自每个表中值不同的列和值。
限制结果
使用 max()
方法限制要处理的不同数量。或者,您可以从传递给 each()
的函数返回 false
来在任何时候终止处理。
计算结果
output()
和 each()
方法都返回已处理的差异结果数,但如果您希望在处理记录之前获取此数字,请使用 count()
。这利用了 SQL 的 COUNT
聚合函数,以避免向您的服务器返回大量数据。
模糊匹配
DBDiff 使用您的底层数据库进行比较,通常涉及严格比较。这对于许多用例(如比较备份之间的更改)非常完美。但是,在其他时候,您可能希望对数据中的差异更加宽容。
想象你正在比较两个联系名单。除了找到新的联系人外,你还想检测联系人姓名更改的情况。然而,你的名单是由人工生成的,可能包含你想忽略的打字错误和其他微小差异。
虽然你可以自己编写逻辑,但DBDiff为此提供了两种方便的策略:规范化器和比较器。
规范化器
规范化器是一种方法,它接受一个值并返回一个修改后的版本。DBDiff将在将两个值都通过规范化器后进行比较,这样你就能够控制比较过程。
例如,我们可以通过告诉usingNormalizers()
方法在所需列上运行本地的trim()
函数来忽略首尾空格。
$diff->usingNormalizers([
'name' => 'trim'
]);
如果你指定了多个函数,它们将按顺序执行。为了在去除空格后执行不区分大小写的比较
$diff-> usingNormalizers([
'name' => ['trim', 'mb_strtolower']
]);
你也可以提供自己的函数。例如,如果你的某些名字以头衔开头,你可以忽略它们
$titles = '/^(mr|mrs|dr)\s+/';
$ignore_titles = function($value) use ($titles) {
return preg_replace($titles, '', $value);
};
$diff-> usingNormalizers([
'name' => ['trim', 'mb_strtolower', $ignore_titles]
]);
比较器
规范化器在值被规范化后仍然使用严格的比较。另一方面,比较器为你提供两个值以供你自己进行比较。
例如,假设我们想要忽略用户由于简单的打字错误而输入的姓名。我们可以计算两个姓名之间的levenshtein
距离,如果它达到了一个阈值则返回true
$tolerate_typos = function($a, $b) {
return levenshtein($a, $b) <= 1;
};
$diff->usingComparators([
'name' => $tolerate_typos
]);
你还可以结合这两种策略
$diff->usingNormalizers([
'name' => ['trim', 'mb_strtolower', $ignore_titles]
])->usingComparators([
'name' => $tolerate_typos
]);