Laravel 基于另一列的可空迁移
Laravel Migration Nullable Based on Another Column
我正在使用 Laravel 编写数据库迁移,我想知道是否可以根据另一列的值将一列设置为不可空。
例如:
If User.owns_cat === true
Then User.cat_name->nullable(false)
我知道我可以稍后通过验证规则来处理这个问题,但我想在数据库级别使用这个规则。
您真正需要的是支持条件函数依赖和关联规则。
关联规则 (AR)
c => f(A)
其中 c 是一个逻辑上可确定的值,如果满足,则列集 A 将填充某些内容
A = (A1, A2, ..., An)
条件函数依赖(CFD)
c => A -> B
其中c是逻辑上可确定的值,如果满足,则列集A确定列集B的值,其中
A = (A1, A2, ..., An)
和
B = (B1, B2, ..., Bn)
问题
RDBMS 系统不倾向于开箱即用地支持 AR 或 CFD,至少我上次检查时是这样。因此,由于底层系统可能不支持您需要的功能,Laravel 迁移也可能无法实现。
解决方案
基于应用程序代码定义模式的问题在于,这项任务在技术堆栈的 ORM 级别上并不太合适,因为:
- 你使用了一些你只能间接影响的模式生成器
- 更复杂的问题很难通过这样的系统解决
- 模式更改生成器可能存在错误,这会不必要地增加您对问题的担忧
那么,你可以做什么:
- 您可以在应用程序级别实现检查某些条件的功能,如果条件满足,则执行规则,也就是说,如果违反规则,则抛出错误或设置默认值,而如果满足规则,则调用 set
- 您可以在数据库中实现一个触发器,它会在 insert/update 之前检查并执行您需要的规则
- 架构解决方案
- 定期运行数据修复
触发器
您将创建一个触发器,它会检查 column2 的值,如果满足您的条件,则检查 column1 是否为空。如果是这样,那么您可能会选择抛出错误或设置默认值。
优点:即使写入操作发生在您的应用程序之外,您的数据一致性也将保持。
缺点:如果规则频繁更改,这将很难维护,并且无法访问您的应用程序级资源。
这种方法是否适合您,取决于您的需要。
架构解决方案
因此,如果 c1 具有某些值,则 c2 不可为 null。您可以将 c1 移动到另一个 table 并使 c2 成为外键。如果满足 c1 的条件,请确保 c2 是包含 c1.
的新 table 的正确外键
优点:您只使用 RDBMS 开箱即用的资源
缺点:如果你的 c2 条件很复杂,这种方法是违反直觉的
此方法的适用性取决于您病情的复杂程度。
定期运行数据修复
您可以允许暂时不符合您的规则,并定期自动解决问题。
优点:解决方案可能是对数据库服务器的单个请求,它会执行存储过程或类似的东西,快速执行任务。
缺点:你不能指望你的规则每时每刻都在每条记录上得到执行。
如果您不担心您的规则会被暂时违反,只要它很快就会纠正,这就是适用的。
应用程序级支持
您可以实现具有 set 方法的 class。该 set 方法将获得一个实体和一个 returns 布尔值的函数。如果函数returns为真,则调用set。否则抛出异常或设置默认值。
我正在使用 Laravel 编写数据库迁移,我想知道是否可以根据另一列的值将一列设置为不可空。
例如:
If User.owns_cat === true
Then User.cat_name->nullable(false)
我知道我可以稍后通过验证规则来处理这个问题,但我想在数据库级别使用这个规则。
您真正需要的是支持条件函数依赖和关联规则。
关联规则 (AR)
c => f(A)
其中 c 是一个逻辑上可确定的值,如果满足,则列集 A 将填充某些内容
A = (A1, A2, ..., An)
条件函数依赖(CFD)
c => A -> B
其中c是逻辑上可确定的值,如果满足,则列集A确定列集B的值,其中
A = (A1, A2, ..., An)
和
B = (B1, B2, ..., Bn)
问题
RDBMS 系统不倾向于开箱即用地支持 AR 或 CFD,至少我上次检查时是这样。因此,由于底层系统可能不支持您需要的功能,Laravel 迁移也可能无法实现。
解决方案
基于应用程序代码定义模式的问题在于,这项任务在技术堆栈的 ORM 级别上并不太合适,因为:
- 你使用了一些你只能间接影响的模式生成器
- 更复杂的问题很难通过这样的系统解决
- 模式更改生成器可能存在错误,这会不必要地增加您对问题的担忧
那么,你可以做什么:
- 您可以在应用程序级别实现检查某些条件的功能,如果条件满足,则执行规则,也就是说,如果违反规则,则抛出错误或设置默认值,而如果满足规则,则调用 set
- 您可以在数据库中实现一个触发器,它会在 insert/update 之前检查并执行您需要的规则
- 架构解决方案
- 定期运行数据修复
触发器
您将创建一个触发器,它会检查 column2 的值,如果满足您的条件,则检查 column1 是否为空。如果是这样,那么您可能会选择抛出错误或设置默认值。
优点:即使写入操作发生在您的应用程序之外,您的数据一致性也将保持。
缺点:如果规则频繁更改,这将很难维护,并且无法访问您的应用程序级资源。
这种方法是否适合您,取决于您的需要。
架构解决方案
因此,如果 c1 具有某些值,则 c2 不可为 null。您可以将 c1 移动到另一个 table 并使 c2 成为外键。如果满足 c1 的条件,请确保 c2 是包含 c1.
的新 table 的正确外键优点:您只使用 RDBMS 开箱即用的资源
缺点:如果你的 c2 条件很复杂,这种方法是违反直觉的
此方法的适用性取决于您病情的复杂程度。
定期运行数据修复
您可以允许暂时不符合您的规则,并定期自动解决问题。
优点:解决方案可能是对数据库服务器的单个请求,它会执行存储过程或类似的东西,快速执行任务。
缺点:你不能指望你的规则每时每刻都在每条记录上得到执行。
如果您不担心您的规则会被暂时违反,只要它很快就会纠正,这就是适用的。
应用程序级支持
您可以实现具有 set 方法的 class。该 set 方法将获得一个实体和一个 returns 布尔值的函数。如果函数returns为真,则调用set。否则抛出异常或设置默认值。