【问题标题】:How do I run inspectdb against different schemas in oracle?如何针对 oracle 中的不同模式运行 inspectdb?
【发布时间】:2012-08-06 17:10:58
【问题描述】:

我想针对 Oracle 数据库运行 inspectdb。我使用的用户帐户是拥有 0 个表的只读用户。但是,它可以访问包含所有表的模式。使用inspectdb时如何指定架构?

我目前的命令是:python manage.py inspectdb --database "oradb" > test_model.py

这只会输出带有from django.db import models 的文件。

【问题讨论】:

    标签: django oracle inspectdb


    【解决方案1】:

    尝试通过在 settings.py 的 DATABASES 变量中添加一个选项来指定 search_path,如下所示:

    'OPTIONS': {
           'options': '-c search_path=myschema'
    }
    

    完整的 DATABASES 变量应该是:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': 'mydatabase',
            'USER': 'postgres',
            'PASSWORD': 'mypassword',
            'HOST': 'localhost',
            'PORT': '5432',
            'OPTIONS': {
                'options': '-c search_path=myschema'
            }
        }
    }
    

    之后python migrate inspectdb 应该可以在您的架构上运行

    【讨论】:

    • 问题是如何在 Oracle 而不是 Postgresql 中检查模式。
    • 谢谢你的提示,它对我有帮助。
    【解决方案2】:

    关于 Oracle 支持,César 的回答是正确的。但是,通过在两个地方修改django\db\backends\oracle\introspection.py,我能够生成一个粗略的模型。

    get_table_list中的cursor.execute行改为:

    cursor.execute("SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'OTHERSCHEMA'")
    

    get_table_description 中第一行cursor.execute 中的user_table_cols 更改为ALL_TAB_COLUMNS 以阅读:

    cursor.execute("""
            SELECT
                column_name,
                data_default,
                CASE
                    WHEN char_used IS NULL THEN data_length
                    ELSE char_length
                END as internal_size
            FROM ALL_TAB_COLUMNS
            WHERE table_name = UPPER(%s)""", [table_name])
    

    接下来,将get_table_description 中的第二行cursor.execute 更改为:cursor.execute("SELECT * FROM OTHERSCHEMA.%s WHERE ROWNUM < 2" % self.connection.ops.quote_name(table_name))

    由于这是一个旧数据库,其中策略阻止对数据库进行更改,这对于一次性运行很有好处。

    模型完成后还需要进行一些更改。我的一些类似乎缺少主键引用和外键引用。我会手动添加这些。

    我所做的最后一项更改是修改所有 class Meta: 实例以引用正确的架构:

    class Meta:
        db_table = u'"SCHEMA"."TABLE_NAME"'     # Notice the quoting needed
    

    【讨论】:

    • 它对我有用。使用 inspectdb 后,我恢复更改。我在模型中使用了 db_column,以便 django 正确识别 ForeignKeys。
    【解决方案3】:

    问题是 Django 的 inspectdb 不支持 Oracle。来自文档:

    inspectdb 适用于 PostgreSQL、MySQL 和 SQLite。外键 检测仅适用于 PostgreSQL 和某些类型的 MySQL 表格。

    --database 选项可用于指定数据库 反省。

    【讨论】:

      【解决方案4】:

      如果有人遇到此线程:Andy 的建议 + 我还更改了 get_relations 方法以在生成的源中获取外键,适用于 1.9.1:

          def get_relations(self, cursor, table_name):
          """
          Returns a dictionary of {field_name: (field_name_other_table, other_table)}
          representing all relationships to the given table.
          """
          table_name = table_name.upper()
      
          cursor.execute("""
              SELECT a.column_name, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
                FROM all_cons_columns a
                JOIN all_constraints c ON a.owner = c.owner
                                      AND a.constraint_name = c.constraint_name
                JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
                                         AND c.r_constraint_name = c_pk.constraint_name
               WHERE c.constraint_type = 'R'
                 AND a.table_name = %s""", [table_name])
      
          relations = {}
          for row in cursor.fetchall():
              relations[row[0].lower()] = (row[2].lower(), row[1].lower())
          return relations
      

      【讨论】:

        【解决方案5】:

        我的两分钱。(django 版本 1.9.7 + django GIS 扩展)

        按照 Andy 和 Mirek Simek 的建议,我进一步修改:

        settings.py

        的数据库配置中添加 'schemas'
            ...
            'oracle1': {
                'ENGINE': 'django.contrib.gis.db.backends.oracle',
                'NAME': 'dbname',
                'USER': 'dbuser',
                'PASSWORD': 'dbpass',
                'HOST': 'dbhostname',
                'PORT': 'dbport',
                'schemas': ['SCHEMANAME1', ....] #<-- this
            }, 
            ...
        

        以这种方式修改get_tables_list

        def get_table_list(self, cursor):
            """
            Returns a list of table and view names in the current database.
            """
            cursor.execute("SELECT TABLE_NAME, 't' FROM USER_TABLES UNION ALL "
                           "SELECT VIEW_NAME, 'v' FROM USER_VIEWS")
            res = [TableInfo(row[0].lower(), row[1]) for row in cursor.fetchall()]
        
            schemas = self.connection.settings_dict.get('schemas')
            if schemas and len(schemas)>0:
                for s in schemas:
                    cursor.execute("SELECT TABLE_NAME, 't' FROM ALL_TABLES WHERE OWNER = '%s'" %s)
                    for row in cursor.fetchall():
                        tbl_name, typ = '.'.join([s,row[0].lower()]), row[1]
                        try:
                            # let us check for permission to query
                            cursor.execute("SELECT * FROM %s WHERE ROWNUM < 1" % tbl_name.upper())
                        except DatabaseError, e:
                            pass
                        else:
                            res.append(TableInfo(tbl_name, typ))
            return res
        

        因为我使用的是 gis,所以我不得不为 django/contrib/gis/db/backends/oracle/introspection.py 打一个脏补丁(由于数据库问题,我不知道是否需要它)

        刚刚在 get_geometry_type

        的末尾添加了这个
            ...
                dim = len(dim)
                if dim != 2:
                    field_params['dim'] = dim
            except:  # <-- this
                pass # <-- this
            finally:
                cursor.close()
            ...
        

        【讨论】:

          猜你喜欢
          • 2014-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-28
          • 2019-05-16
          • 1970-01-01
          相关资源
          最近更新 更多