将 Oracle 数据类型转换为 SQLAlchemy 类型
Convert Oracle Datatypes to SQLAlchemy Types
我有一个 oracle 数据类型列表(数百个),我想以编程方式将其映射到 SQLAlchemy 数据类型。
一些示例 oracle 数据类型(以及许多其他数据类型)是:
XMLTYPE
VARCHAR2
UROWID
URITYPE
UNDEFINED
TIMESTAMP(9)
我正在将 oracle 中的数据查询到 pandas 数据帧中,然后使用 sql alchemy 将该数据加载到另一个系统。但是我需要指定目标系统中的目标数据类型。 (由于 ETL 过程被批处理,仅使用数据框默认值不起作用;第一批值可能会“误导”数据类型。)
Here 是 SQLAlchemy 数据类型的列表,我需要将 oracle 数据类型映射到 sqlalchemy 数据类型。除了手动构建这样的字典之外,还有其他优雅的方法吗?
编辑:我给出的具体示例数据类型并不重要。我宁愿以编程方式和动态地将 Oracle 中的任意列分配给正确的 SQLAlchemy 数据类型。数据类型是对
的响应
SELECT
DISTINCT data_type
FROM
all_tab_columns;
返回了超过 150 个值。所以我真的更愿意避免手动查找每个文档。
XMLTYPE
数据类型有 getStringVal
和 getClobVal
方法(取决于内容的长度),您可以使用它们来提取 XML内容只是一个字符串值,可以使用 sqlalchemy.types.Text
(在调用 getClobVal
方法之后)。
VARCHAR2
只是一个可变长度的字符串。 Oracle 没有 VARCHAR
数据类型,这是它的等价物(VARCHAR
目前是 VARCHAR2
的同义词)。等价于 sqlalchemy.types.String
.
UROWID
记录为:
Each row in a database has an address. However, the rows of some tables have addresses that are not physical or permanent or were not generated by Oracle Database. For example, the row addresses of index-organized tables are stored in index leaves, which can move. Rowids of foreign tables (such as DB2 tables accessed through a gateway) are not standard Oracle rowids.
Oracle uses universal rowids (urowids) to store the addresses of index-organized and foreign tables. Index-organized tables have logical urowids and foreign tables have foreign urowids. Both types of urowid are stored in the ROWID
pseudocolumn (as are the physical rowids of heap-organized tables).
在数据库外持久化一个 UROWID
是没有意义的,因为它代表的数据可能不是永久的,可能会移动,即使它不移动,它也只是代表一个内存位置,而不是任何实际数据。
URITYPE
表示 URI
到另一个资源,您可以使用它的 getURL
方法来获取它代表的 URI,应该只是一个字符串值。等效的数据类型为 sqlalchemy.types.String
或 sqlalchemy.types.Text
(在调用 getURL
方法以获取字符串表示之后)。
UNDEFINED
不是数据类型。您应该检查是否有人创建了名为 UNDEFINED
.
的用户定义类型
TIMESTAMP(9)
只是一个 TIMESTAMP
,精度为 9
十进制秒数。从文档中,您似乎想要 sqlalchemy.dialects.oracle.DATE
.
The datatypes are the response to
SELECT DISTINCT data_type FROM all_tab_columns;
请不要依赖此列表,因为它包括 *SYS
模式的表中使用的所有数据类型,您不应接触其中的大部分表,因为更改它们可能会产生无法预料的后果(包括使你的数据库无法使用)。
这些数据类型中的大多数将成为数据库内部工作中使用的私有数据类型;您可以确定它们,因为它们通常在类型名称中有一个 $
。下一个最常见的分组是 SDO 几何数据类型,它们都有 SDO_
前缀。
因此,如果您的查询变为:
SELECT CASE
WHEN data_type LIKE '%$%' THEN 'Private Type'
WHEN data_type LIKE 'SDO_%' THEN 'SDO Geometry Type'
ELSE data_type
END AS data_type,
COUNT( DISTINCT data_type ) AS num_instances
FROM all_tab_columns
GROUP BY
CASE
WHEN data_type LIKE '%$%' THEN 'Private Type'
WHEN data_type LIKE 'SDO_%' THEN 'SDO Geometry Type'
ELSE data_type
END
ORDER BY num_instances DESC, data_type ASC;
然后,在 db<>fiddle 上,您将获得此输出,用户生成的表为零(因此仅针对系统生成的表):
DATA_TYPE | NUM_INSTANCES
:--------------------------- | ------------:
Private Type | 130
SDO Geometry Type | 5
ANYDATA | 1
BINARY_DOUBLE | 1
BLOB | 1
CHAR | 1
CLOB | 1
DATE | 1
DS_VARRAY_4_CLOB | 1
FLOAT | 1
HSBLKNAMLST | 1
HSBLKVALARY | 1
INTERVAL DAY(3) TO SECOND(0) | 1
INTERVAL DAY(3) TO SECOND(2) | 1
INTERVAL DAY(9) TO SECOND(6) | 1
LONG | 1
LONG RAW | 1
NUMBER | 1
NVARCHAR2 | 1
RAW | 1
ROWID | 1
TIMESTAMP(0) | 1
TIMESTAMP(3) | 1
TIMESTAMP(6) | 1
TIMESTAMP(6) WITH TIME ZONE | 1
TIMESTAMP(9) | 1
UNDEFINED | 1
VARCHAR2 | 1
XMLTYPE | 1
162 种数据类型中有 130 种是私有的,另外 5 种是 SDO 几何类型。
调查其他“有趣的类型”:
SELECT owner, table_name, column_name, data_type
FROM ALL_TAB_COLUMNS
WHERE data_type IN ( 'UNDEFINED', 'HSBLKVALARY', 'HSBLKNAMLST', 'ROWID', 'ANYDATA', 'DS_VARRAY_4_CLOB' )
ORDER BY owner, table_name, data_type
输出:
OWNER | TABLE_NAME | COLUMN_NAME | DATA_TYPE
:----- | :---------------------------- | :-------------------- | :---------------
CTXSYS | CTX_USER_PENDING | PND_ROWID | ROWID
CTXSYS | DRV$PENDING | PND_ROWID | ROWID
CTXSYS | DRV$UNINDEXED | UNX_ROWID | ROWID
CTXSYS | DRV$UNINDEXED2 | UNX_ROWID | ROWID
CTXSYS | DRV$WAITING | WTG_ROWID | ROWID
MDSYS | SDO_GR_MOSAIC_0 | RID | ROWID
MDSYS | SDO_GR_MOSAIC_1 | RID | ROWID
MDSYS | SDO_GR_MOSAIC_2 | RID | ROWID
SYS | ALL_SCHEDULER_JOB_ARGS | ANYDATA_VALUE | ANYDATA
SYS | ALL_SCHEDULER_PROGRAM_ARGS | DEFAULT_ANYDATA_VALUE | ANYDATA
SYS | ALL_SQLSET_BINDS | VALUE | ANYDATA
SYS | ALL_STREAMS_MESSAGE_CONSUMERS | NOTIFICATION_CONTEXT | ANYDATA
SYS | ALL_SUMDELTA | HIGHROWID | ROWID
SYS | ALL_SUMDELTA | LOWROWID | ROWID
SYS | HS$_PARALLEL_METADATA | PARTITION_COL_TYPES | HSBLKNAMLST
SYS | HS$_PARALLEL_METADATA | PARTITION_COL_NAMES | HSBLKNAMLST
SYS | HS_PARALLEL_METADATA | PARTITION_COL_NAMES | HSBLKNAMLST
SYS | HS_PARALLEL_METADATA | PARTITION_COL_TYPES | HSBLKNAMLST
SYS | HS_PARALLEL_PARTITION_DATA | PARTITION_COL_TYPES | HSBLKNAMLST
SYS | HS_PARALLEL_PARTITION_DATA | PARTITION_COL_NAMES | HSBLKNAMLST
SYS | HS_PARALLEL_PARTITION_DATA | HIGH_VALUE | HSBLKVALARY
SYS | HS_PARALLEL_PARTITION_DATA | LOW_VALUE | HSBLKVALARY
SYS | ORA_KGLR7_IDL_SB4 | PIECE | UNDEFINED
SYS | ORA_KGLR7_IDL_UB2 | PIECE | UNDEFINED
SYS | USER_COMPARISON_ROW_DIF | LOCAL_ROWID | ROWID
SYS | USER_COMPARISON_ROW_DIF | REMOTE_ROWID | ROWID
SYS | USER_PARALLEL_EXECUTE_CHUNKS | END_ROWID | ROWID
SYS | USER_PARALLEL_EXECUTE_CHUNKS | START_ROWID | ROWID
SYS | USER_SCHEDULER_JOB_ARGS | ANYDATA_VALUE | ANYDATA
SYS | USER_SCHEDULER_PROGRAM_ARGS | DEFAULT_ANYDATA_VALUE | ANYDATA
SYS | USER_SQLSET_BINDS | VALUE | ANYDATA
SYS | USER_SQLTUNE_BINDS | VALUE | ANYDATA
SYS | USER_SR_STLOG_EXCEPTIONS | BAD_ROWID | ROWID
SYS | USER_SUBSCR_REGISTRATIONS | ANY_CONTEXT | ANYDATA
SYS | _USER_COMPARISON_ROW_DIF | RMT_ROWID | ROWID
SYS | _USER_COMPARISON_ROW_DIF | LOC_ROWID | ROWID
SYS | _user_stat_varray | CL1 | DS_VARRAY_4_CLOB
XDB | XDB$ROOT_INFO_V | RESOURCE_ROOT | ROWID
这些都是 *SYS
表或私有表,您几乎肯定永远不会想直接与它们交互。
UNDEFINED
类型很有趣,因为它似乎未定义:
SELECT owner, type_name
FROM ALL_TYPES
WHERE TYPE_NAME = 'UNDEFINED';
Returns 零行和:
CREATE TABLE TABLE_NAME ( id UNDEFINED );
引发异常 ORA-00902: invalid datatype
。
如何更好地确定您正在使用的类型?只需查看您创建的架构:
SELECT DISTINCT owner, data_type
FROM all_tab_columns
WHERE owner IN ( 'USER1', 'USER2', 'USER3' )
那么您就知道这些数据类型是您的用户创建的表中使用的数据类型。您应该发现,除非您正在做一些深奥的事情,否则您使用的大多数(如果不是全部)类型将由 SQLAlchemy 本机处理。
db<>fiddle here
我有一个 oracle 数据类型列表(数百个),我想以编程方式将其映射到 SQLAlchemy 数据类型。
一些示例 oracle 数据类型(以及许多其他数据类型)是:
XMLTYPE
VARCHAR2
UROWID
URITYPE
UNDEFINED
TIMESTAMP(9)
我正在将 oracle 中的数据查询到 pandas 数据帧中,然后使用 sql alchemy 将该数据加载到另一个系统。但是我需要指定目标系统中的目标数据类型。 (由于 ETL 过程被批处理,仅使用数据框默认值不起作用;第一批值可能会“误导”数据类型。)
Here 是 SQLAlchemy 数据类型的列表,我需要将 oracle 数据类型映射到 sqlalchemy 数据类型。除了手动构建这样的字典之外,还有其他优雅的方法吗?
编辑:我给出的具体示例数据类型并不重要。我宁愿以编程方式和动态地将 Oracle 中的任意列分配给正确的 SQLAlchemy 数据类型。数据类型是对
的响应SELECT
DISTINCT data_type
FROM
all_tab_columns;
返回了超过 150 个值。所以我真的更愿意避免手动查找每个文档。
XMLTYPE
数据类型有getStringVal
和getClobVal
方法(取决于内容的长度),您可以使用它们来提取 XML内容只是一个字符串值,可以使用sqlalchemy.types.Text
(在调用getClobVal
方法之后)。VARCHAR2
只是一个可变长度的字符串。 Oracle 没有VARCHAR
数据类型,这是它的等价物(VARCHAR
目前是VARCHAR2
的同义词)。等价于sqlalchemy.types.String
.UROWID
记录为:Each row in a database has an address. However, the rows of some tables have addresses that are not physical or permanent or were not generated by Oracle Database. For example, the row addresses of index-organized tables are stored in index leaves, which can move. Rowids of foreign tables (such as DB2 tables accessed through a gateway) are not standard Oracle rowids.
Oracle uses universal rowids (urowids) to store the addresses of index-organized and foreign tables. Index-organized tables have logical urowids and foreign tables have foreign urowids. Both types of urowid are stored in the
ROWID
pseudocolumn (as are the physical rowids of heap-organized tables).在数据库外持久化一个
UROWID
是没有意义的,因为它代表的数据可能不是永久的,可能会移动,即使它不移动,它也只是代表一个内存位置,而不是任何实际数据。URITYPE
表示URI
到另一个资源,您可以使用它的getURL
方法来获取它代表的 URI,应该只是一个字符串值。等效的数据类型为sqlalchemy.types.String
或sqlalchemy.types.Text
(在调用getURL
方法以获取字符串表示之后)。
的用户定义类型UNDEFINED
不是数据类型。您应该检查是否有人创建了名为UNDEFINED
.TIMESTAMP(9)
只是一个TIMESTAMP
,精度为9
十进制秒数。从文档中,您似乎想要sqlalchemy.dialects.oracle.DATE
.
The datatypes are the response to
SELECT DISTINCT data_type FROM all_tab_columns;
请不要依赖此列表,因为它包括 *SYS
模式的表中使用的所有数据类型,您不应接触其中的大部分表,因为更改它们可能会产生无法预料的后果(包括使你的数据库无法使用)。
这些数据类型中的大多数将成为数据库内部工作中使用的私有数据类型;您可以确定它们,因为它们通常在类型名称中有一个 $
。下一个最常见的分组是 SDO 几何数据类型,它们都有 SDO_
前缀。
因此,如果您的查询变为:
SELECT CASE
WHEN data_type LIKE '%$%' THEN 'Private Type'
WHEN data_type LIKE 'SDO_%' THEN 'SDO Geometry Type'
ELSE data_type
END AS data_type,
COUNT( DISTINCT data_type ) AS num_instances
FROM all_tab_columns
GROUP BY
CASE
WHEN data_type LIKE '%$%' THEN 'Private Type'
WHEN data_type LIKE 'SDO_%' THEN 'SDO Geometry Type'
ELSE data_type
END
ORDER BY num_instances DESC, data_type ASC;
然后,在 db<>fiddle 上,您将获得此输出,用户生成的表为零(因此仅针对系统生成的表):
DATA_TYPE | NUM_INSTANCES :--------------------------- | ------------: Private Type | 130 SDO Geometry Type | 5 ANYDATA | 1 BINARY_DOUBLE | 1 BLOB | 1 CHAR | 1 CLOB | 1 DATE | 1 DS_VARRAY_4_CLOB | 1 FLOAT | 1 HSBLKNAMLST | 1 HSBLKVALARY | 1 INTERVAL DAY(3) TO SECOND(0) | 1 INTERVAL DAY(3) TO SECOND(2) | 1 INTERVAL DAY(9) TO SECOND(6) | 1 LONG | 1 LONG RAW | 1 NUMBER | 1 NVARCHAR2 | 1 RAW | 1 ROWID | 1 TIMESTAMP(0) | 1 TIMESTAMP(3) | 1 TIMESTAMP(6) | 1 TIMESTAMP(6) WITH TIME ZONE | 1 TIMESTAMP(9) | 1 UNDEFINED | 1 VARCHAR2 | 1 XMLTYPE | 1
162 种数据类型中有 130 种是私有的,另外 5 种是 SDO 几何类型。
调查其他“有趣的类型”:
SELECT owner, table_name, column_name, data_type
FROM ALL_TAB_COLUMNS
WHERE data_type IN ( 'UNDEFINED', 'HSBLKVALARY', 'HSBLKNAMLST', 'ROWID', 'ANYDATA', 'DS_VARRAY_4_CLOB' )
ORDER BY owner, table_name, data_type
输出:
OWNER | TABLE_NAME | COLUMN_NAME | DATA_TYPE :----- | :---------------------------- | :-------------------- | :--------------- CTXSYS | CTX_USER_PENDING | PND_ROWID | ROWID CTXSYS | DRV$PENDING | PND_ROWID | ROWID CTXSYS | DRV$UNINDEXED | UNX_ROWID | ROWID CTXSYS | DRV$UNINDEXED2 | UNX_ROWID | ROWID CTXSYS | DRV$WAITING | WTG_ROWID | ROWID MDSYS | SDO_GR_MOSAIC_0 | RID | ROWID MDSYS | SDO_GR_MOSAIC_1 | RID | ROWID MDSYS | SDO_GR_MOSAIC_2 | RID | ROWID SYS | ALL_SCHEDULER_JOB_ARGS | ANYDATA_VALUE | ANYDATA SYS | ALL_SCHEDULER_PROGRAM_ARGS | DEFAULT_ANYDATA_VALUE | ANYDATA SYS | ALL_SQLSET_BINDS | VALUE | ANYDATA SYS | ALL_STREAMS_MESSAGE_CONSUMERS | NOTIFICATION_CONTEXT | ANYDATA SYS | ALL_SUMDELTA | HIGHROWID | ROWID SYS | ALL_SUMDELTA | LOWROWID | ROWID SYS | HS$_PARALLEL_METADATA | PARTITION_COL_TYPES | HSBLKNAMLST SYS | HS$_PARALLEL_METADATA | PARTITION_COL_NAMES | HSBLKNAMLST SYS | HS_PARALLEL_METADATA | PARTITION_COL_NAMES | HSBLKNAMLST SYS | HS_PARALLEL_METADATA | PARTITION_COL_TYPES | HSBLKNAMLST SYS | HS_PARALLEL_PARTITION_DATA | PARTITION_COL_TYPES | HSBLKNAMLST SYS | HS_PARALLEL_PARTITION_DATA | PARTITION_COL_NAMES | HSBLKNAMLST SYS | HS_PARALLEL_PARTITION_DATA | HIGH_VALUE | HSBLKVALARY SYS | HS_PARALLEL_PARTITION_DATA | LOW_VALUE | HSBLKVALARY SYS | ORA_KGLR7_IDL_SB4 | PIECE | UNDEFINED SYS | ORA_KGLR7_IDL_UB2 | PIECE | UNDEFINED SYS | USER_COMPARISON_ROW_DIF | LOCAL_ROWID | ROWID SYS | USER_COMPARISON_ROW_DIF | REMOTE_ROWID | ROWID SYS | USER_PARALLEL_EXECUTE_CHUNKS | END_ROWID | ROWID SYS | USER_PARALLEL_EXECUTE_CHUNKS | START_ROWID | ROWID SYS | USER_SCHEDULER_JOB_ARGS | ANYDATA_VALUE | ANYDATA SYS | USER_SCHEDULER_PROGRAM_ARGS | DEFAULT_ANYDATA_VALUE | ANYDATA SYS | USER_SQLSET_BINDS | VALUE | ANYDATA SYS | USER_SQLTUNE_BINDS | VALUE | ANYDATA SYS | USER_SR_STLOG_EXCEPTIONS | BAD_ROWID | ROWID SYS | USER_SUBSCR_REGISTRATIONS | ANY_CONTEXT | ANYDATA SYS | _USER_COMPARISON_ROW_DIF | RMT_ROWID | ROWID SYS | _USER_COMPARISON_ROW_DIF | LOC_ROWID | ROWID SYS | _user_stat_varray | CL1 | DS_VARRAY_4_CLOB XDB | XDB$ROOT_INFO_V | RESOURCE_ROOT | ROWID
这些都是 *SYS
表或私有表,您几乎肯定永远不会想直接与它们交互。
UNDEFINED
类型很有趣,因为它似乎未定义:
SELECT owner, type_name
FROM ALL_TYPES
WHERE TYPE_NAME = 'UNDEFINED';
Returns 零行和:
CREATE TABLE TABLE_NAME ( id UNDEFINED );
引发异常 ORA-00902: invalid datatype
。
如何更好地确定您正在使用的类型?只需查看您创建的架构:
SELECT DISTINCT owner, data_type
FROM all_tab_columns
WHERE owner IN ( 'USER1', 'USER2', 'USER3' )
那么您就知道这些数据类型是您的用户创建的表中使用的数据类型。您应该发现,除非您正在做一些深奥的事情,否则您使用的大多数(如果不是全部)类型将由 SQLAlchemy 本机处理。
db<>fiddle here