sql >> データベース >  >> RDS >> Mysql

DjangoManyToManyと複数のデータベース

    Django 1.6+のソリューションが存在します (1.11を含む) MySQL の場合 およびsqlite バックエンド、オプションForeignKey。 db_constraint =誤り 明示的なMeta.db_table 。データベース名とテーブル名が引用されている場合 '`'(MySQLの場合)または''"'(他のdbの場合)、例:db_table = '"db2"."table2"' )。その後、それ以上引用されず、ドットは引用外になります。有効なクエリはDjangoORMによってコンパイルされます。より適切なソリューションは、db_table = 'db2"."table2'です。 (これにより、結合が可能になるだけでなく、db制約の移行に近い1つの問題も発生します)

    db2_name = settings.DATABASES['db2']['NAME']
    
    class Table1(models.Model):
        fk = models.ForeignKey('Table2', on_delete=models.DO_NOTHING, db_constraint=False)
    
    class Table2(models.Model):
        name = models.CharField(max_length=10)
        ....
        class Meta:    
            db_table = '`%s`.`table2`' % db2_name  # for MySQL
            # db_table = '"db2"."table2"'          # for all other backends
            managed = False
    

    クエリセット:

    >>> qs = Table2.objects.all()
    >>> str(qs.query)
    'SELECT "DB2"."table2"."id" FROM DB2"."table2"'
    >>> qs = Table1.objects.filter(fk__name='B')
    >>> str(qs.query)
    SELECT "app_table1"."id"
        FROM "app_table1"
        INNER JOIN "db2"."app_table2" ON ( "app_table1"."fk_id" = "db2"."app_table2"."id" )
        WHERE "db2"."app_table2"."b" = 'B'
    

    そのクエリ解析は、すべてのデータベースバックエンドでサポートされています ただし、Djangoでは、他の必要な手順についてバックエンドで個別に話し合う必要があります。 同様の重要な質問

    Djangoは参照整合性制約を作成できないため、オプション'db_constraint'が移行に必要です。
    ADD foreign key table1(fk_id) REFERENCES db2.table2(id)
    ただし、手動で作成できます MySQLの場合。

    特定のバックエンドに関する質問は、実行時に別のデータベースをデフォルトに接続できるかどうか、およびデータベース間の外部キーがサポートされているかどうかです。これらのモデルも書き込み可能です。間接的に接続されたデータベースは、managed=Falseのレガシーデータベースとして使用する必要があります (テーブルdjango_migrationsが1つしかないため 移行の追跡は、直接接続されたデータベースでのみ作成されます。このテーブルは、同じデータベース内のテーブルのみを記述している必要があります。)ただし、データベースシステムがそのようなインデックスをサポートしている場合、外部キーのインデックスは管理側で自動的に作成できます。

    Sqlite3 :実行時に別のデフォルトのsqlite3データベースに接続する必要があります(answer SQLite-さまざまなデータベースのテーブルをどのように結合しますか )、せいぜいシグナル connection_created

    from django.db.backends.signals import connection_created
    
    def signal_handler(sender, connection, **kwargs):
        if connection.alias == 'default' and connection.vendor == 'sqlite':
            cur = connection.cursor()
            cur.execute("attach '%s' as db2" % db2_name)
            # cur.execute("PRAGMA foreign_keys = ON")  # optional
    
    connection_created.connect(signal_handler)
    

    もちろん、データベースルーターと通常のdjango...ForeignKeyは必要ありません。 db_constraint=Falseで使用できます。利点は、テーブル名がデータベース間で一意である場合、「db_table」が不要なことです。

    MySQL 異なるデータベース間の外部キー 簡単です。 SELECT、INSERT、DELETEなどのすべてのコマンドは、データベース名を事前に添付せずにサポートします。

    この質問は、レガシーデータベースに関するものでした。ただし、移行でも興味深い結果が得られました。



    1. SQLite Total()のしくみ

    2. 別のユーザーアカウント(macOS)からのmySQLインスタンスの回復

    3. SQLは同じフィールドで複数の値を検索します

    4. Postgresqlの複数の列でWHEREINを実行する