Tạo ràng buộc unique với điều kiện trong Laravel và MySQL ?
Xin chào mọi người, mình có 1 vấn đề mong mọi người giúp đỡ. Trong bảng mình muốn 1 trường là unique, mình đã tạo trong migration như sau:
$table->string('code',13)->unique()->nullable();
Và mình cũng đã validate để nó sẽ bỏ qua các bản ghi có trường is_deleted = 1 ( is_deleted = 0 thì sẽ validate không cho phép trùng ).
$rules['code'] = 'nullable|max:13|unique:game,code,null,null,is_deleted,0';
Tuy nhiên nó chỉ pass qua được validate, khi lưu vào DB vẫn sẽ bị báo lỗi do nó đang là unique. Vậy có cách nào để thêm điều kiện vào unique trong mysql không ạ ? Mình muốn nó kiểu như này :
$table->string('code',13)->unique()->where('is_deleted',0)->nullable();
Cảm ơn mọi người đã đọc
2 CÂU TRẢ LỜI
Mình nghĩ việc thêm điều kiện cho unique()
khi định nghĩa bảng không khả thi lắm.
Bạn có thể thử thêm unique constraint cho hai trường code
và is_deleted
(compound index) xem sao, mình nghĩ đây là cách đơn giản nhất. Như vậy thì mình có thể có cùng một mã code cho cả hai trạng thái.
$table->string('code', 13)->nullable();
$table->boolean('is_deleted')->default(false);
$table->unique(['code', 'is_deleted']);
@manhtqb @vinhnguyen Giải quyết theo hướng đặt unique
cho cả 2 trường code
và is_deleted
là một cách rất hay, tuy nhiên nó có thể gặp phải một vấn đề sau này đó là dữ liệu soft delete có thể sẽ không thể restore lại được (do khi restore thì giá trị is_deleted
được thay đổi, có thể sẽ vướng constraint unique
).
Nếu không gặp trường hợp cần phải restore dữ liệu thì có thể theo cách này.
Cách giải quyết khác đơn giản hơn là loại bỏ hoàn toàn contrain unique
trong database đi, nó cũng không cần thiết khi mà bạn đã verify tính unique ở tầng application (trong code laravel) rồi
cảm ơn bác @thang ạ, em cũng nghĩ cách bỏ unique trong DB là tốt nhất. Tuy nhiên trước mắt sẽ sửa như của bác @vinhnguyen
Theo mình thì bạn không thể tạo dữ liệu giống nhau trên cùng một trường mà đã khi set unique trường đó khi create database. Ở đây bạn sử dụng soft delete nên sẽ tạo một trường is_deleted để đánh dấu rằng một bản ghi là active hay inactive, bản chất là dữ liệu vẫn ở đó mà không bị mất đi nên mysql chỉ biết kiểm tra khi bạn lưu vào là cái thằng dữ liệu trường được set unique đã có hay chưa chứ không quan tâm thằng is_deleted. Vậy nên nếu bạn đã muốn sử dụng soft delete thì mình nghĩ bạn nên reset lại database và bỏ unique với trường code kia đia, và mình sẽ check validation khi create hay update để đảm bảo chỉ lưu một thằng code duy nhất.