gbradley/dbdiff

SQL数据库表差异比较

v0.6 2020-09-24 09:54 UTC

This package is auto-updated.

Last update: 2024-09-24 18:15:30 UTC


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
]);