web-dev-qa-db-ja.com

Laravel移行-テーブルにチェック制約を追加する

Laravelこのような移行でテーブルを作成したい-

CREATE TABLE Payroll
(
 ID int PRIMARY KEY, 
 PositionID INT,
 Salary decimal(9,2) 
 CHECK (Salary < 150000.00)
);

私がしたことは-

Schema::create('Payroll', function (Blueprint $table)
{
    $table->increments('id');
    $table->integer('PositionID ');
    $table->decimal('Salary',9,2);
    //$table->timestamps();
});

しかし、私はこれを作成することはできません-

 CHECK (Salary < 150000.00)

このCHECK制約を Laravel Migration に実装する方法を教えてもらえますか?

13
Abrar Jahin

制約の追加はBlueprintクラスではサポートされていません(少なくともLaravel 5.3)の時点では)が、可能ですデータベースステートメントを使用して、移行から直接テーブルに制約を追加します。

移行ファイルで、

public function up ()
{
    Schema::create('payroll', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('position_id');
        $table->decimal('salary',9,2);
    });

    // Add the constraint
    DB::statement('ALTER TABLE payroll ADD CONSTRAINT chk_salary_amount CHECK (salary < 150000.00);');
}
17
Michael

これはLaravel移行の機能ではないと思います。MYSQLに手動で追加しない限り、これはモデルまたは検証ロジックに含まれている必要があると思います。

これは私がすることです

$this->validate($request, [
    'Salary' => 'max:150000.00',
]);
4
Ben Clayton

この機能はBlueprintクラスに含まれていないため、移行ファイルでこれを行うことはできません。

ただし、給与計算モデルでは、ミューテーターを作成できます。

class Payroll extends Model{

    public function setSalaryAttribute($value){
        $this->attributes['Salary'] = $value < 150000.00 ? $value : 150000.00;
    }

}

したがって、給与給与属性が作成または更新されると、このメソッドが自動的にトリガーされ、新しい値が150000.00を超えていないことを確認します。

編集: ミューテーターのドキュメント in Laravel Docs)をご覧ください。

2
Gerard Reches

MySQL/MariadbはCHECK制約を無視するため、代わりにトリガーを使用する必要があります。トリガーは、INSERT/UPDATE/DELETEのいずれかで実行するように設定できます。つまり、INSERTとUPDATEの両方で実行する場合は、プロシージャを作成してから、2つの別々のトリガーから呼び出す必要があります。

DB :: statement()はこの構文をサポートしていないため、代わりにPDO :: exec()を使用する必要があります。

Michaelの例のTRIGGER構文は次のとおりです。

public function up()
{
    Schema::create('Payroll', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('position_id');
        $table->decimal('salary', 9, 2);
    });

    DB::connection()->getPdo()->exec("
        -- Create the procedure
        CREATE PROCEDURE payroll_check_salary_amount (salary INT)
        BEGIN
            IF NOT (salary < 150000.00) THEN
                SIGNAL SQLSTATE '45000' SET message_text = 'salary must be less than 150000.00';
            END IF;
        END;

        -- Create the INSERT trigger
        CREATE TRIGGER payroll_check_salary_amount_insert BEFORE INSERT ON Payroll
        FOR EACH ROW
        BEGIN
            CALL payroll_check_salary_amount(NEW.salary);
        END;

        -- Create the UPDATE trigger
        CREATE TRIGGER payroll_check_salary_amount_update BEFORE UPDATE ON Payroll
        FOR EACH ROW
        BEGIN
            CALL payroll_check_salary_amount(NEW.salary);
        END;
    ");
}

public function down()
{
    Schema::dropIfExists('Payroll');
    DB::statement('DROP PROCEDURE IF EXISTS payroll_check_salary_amount');
}
1

制約を追加するには、次のコードを作成できます

$table->enum('choices', ['foo', 'bar']);

しかし、算術演算で作成したい場合、解決策は** @ Michael **で言及されているようなSQLステートメントで作成することです。

// Add the constraint
DB::statement('ALTER TABLE payroll ADD CONSTRAINT chk_salary_amount CHECK (salary < 150000.00);');

詳細については、以下を確認してください リンク

0
public function up ()
{
    Schema::create('payroll', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('p_id');
        $table->decimal('payment',9,2);
    });

    // Add the constraint`enter code here`
    DB::statement('ALTER TABLE payroll ADD CONSTRAINT check_salary_amount CHECK (payment < 2000.00);');
}