3

Django アプリケーションで MySQL トリガーを作成しようとしています。http://bryanmarty.com/blog/2012/12/03/mysql-triggers-django/の例に従おうとしましたが、カスタム SQL を実行すると、データベースに作成されたトリガーが表示されません (使用してトリガーを表示;)。

私のモデルの名前は Process で、Machine という名前の別のモデルもあります。これは私の「カスタム」SQLがどのように見えるかです:

delimiter |
CREATE TRIGGER processes_running_count
AFTER INSERT ON jobs_process
FOR EACH ROW 
BEGIN
    UPDATE jobs_machine SET processes_running=processes_running+1 limit 1; --
END;
|
delimiter ;

python manage.py syncdb を実行すると、適切なテーブル (jobs_process、jobs_machine など) が存在することがわかりますが、トリガーは存在しません。カスタム SQL のコードをコピーして MySQL プロンプトに貼り付けると、トリガーが作成されます (したがって、問題は無効な MySQL 構文ではないと思います)。

何かアドバイス?

4

2 に答える 2

5

Django でこれを行うための標準的な方法はありません。これは、Model-View-Whatever パラダイム (ビジネス ロジックと永続性の混合)に関する懸念の分離を壊してしまうためです。Django では、トリガーについて考えるほとんどの状況で、Model.save()and/orModel.delete()メソッドをオーバーライドできます ( signal も参照してください)

この場合、トリガーは過剰です。なぜ計算可能な値を保存するのでしょうか? のようなことをするだけですProcess.objects.filter(active=True).count()

「私たちは小さな効率性を忘れるべきです。たとえば、約 97% の時間です。時期尚早の最適化はすべての悪の根源です」 - Knuth、Donald (1974 年 12 月)。「go to ステートメントを使用した構造化プログラミング」

とはいえ、リレーショナル データベースは、 ACIDコントラクトによって課せられるオーバーヘッドのために、ステータス ポーリングに高価な選択肢であるという懸念があるかもしれません。テーブルを叩く数百のクライアントはjobs_machine、ほとんどのサーバーにとってストレスになる可能性があります。redismemcachedなどの軽量のキー/バリュー ストアは、この種のタスクでよく使用されます (これらは巨大な共有辞書と考えてください)。

于 2013-07-02T01:40:37.170 に答える
0

SQLステートメントの乗算区切り記号に関する情報は次のとおりですhttps://stackoverflow.com/a/52292690/9521312

あなたの場合、MySQLステートメントをカスタムDELIMITERで生のSQLステートメントに変換する私のスクリプトを使用できます(そのままでは完全ではありません)。

移行ファイルにスクリプト実行を追加

スクリプトを使用する例は両方あります: run sql file または run raw MySQL statement

from anywhere import migrate_run_sql

operations = [
              migrations.RunPython(migrate_run_sql.run_sql_file('contract_triggers.sql')),
              migrations.RunPython(migrate_run_sql.run_sql(
                                                           """
                                                           DELIMITER $$
                                                           CREATE TRIGGER trigger_name BEFORE INSERT ON table
                                                           FOR EACH ROW
                                                           BEGIN
                                                             IF NEW.number <> 'anynumber' AND NEW.number <> 'anynumber'
                                                               THEN
                                                                 SET NEW.number = 'anynumber';
                                                             END IF;
                                                           END$$
                                                           """
                                                           ))
             ]

スクリプトファイル

# -*- coding: utf-8 -*-
from django.db import connection
import re
from StringIO import StringIO
from django.conf import settings
import os

# this function get raw MySQL statement
def run_sql(sql): 
    def load_data_from_sql(app, schema_editor):
        f = StringIO(sql)
        return _runsql(f)

    return load_data_from_sql

# this function get sql file
def run_sql_file(filename):
    def load_data_from_sql(app, schema_editor):
        filepath = os.path.join(settings.PROJECT_PATH, '../deploy/mysql/', filename)
        with open(filepath, 'rb') as f:
            return _runsql(f)

    return load_data_from_sql

# in this function content splits and checks line by line
def _runsql(f):
    with connection.cursor() as c:
        file_data = f.readlines()
        statement = ''
        delimiter = ';\n'
        for line in file_data:
            if re.findall('DELIMITER', line): # found delimiter
                if re.findall('^\s*DELIMITER\s+(\S+)\s*$', line):
                    delimiter = re.findall('^\s*DELIMITER\s+(\S+)\s*$', line)[0] + '\n'
                    continue
                else:
                    raise SyntaxError('Your usage of DELIMITER is not correct, go and fix it!')
            statement += line // add lines while not met lines with current delimiter
            if line.endswith(delimiter):
                if delimiter != ';\n':
                    statement = statement.replace(';', '; --').replace(delimiter, ';') # found delimiter, add dash symbols (or any symbols you want) for converting MySQL statements with multiply delimiters in SQL statement
                c.execute(statement) # execute current statement
                statement = '' # begin collect next statement

それが役立つことを願っています!

于 2018-09-12T10:35:48.190 に答える