{"id":6754,"date":"2026-04-20T14:09:36","date_gmt":"2026-04-20T12:09:36","guid":{"rendered":"https:\/\/rootfan.com\/?p=6754"},"modified":"2026-04-20T14:29:44","modified_gmt":"2026-04-20T12:29:44","slug":"problemas-y-soluciones-en-la-migracion-de-oracle-a-postgresql","status":"publish","type":"post","link":"https:\/\/rootfan.com\/es\/oracle-to-postgres-migration-issues-and-fixes\/","title":{"rendered":"Migraci\u00f3n de Oracle a Postgres: Problemas y Soluciones del Esquema CO"},"content":{"rendered":"<p>El esquema CO (Customer Orders) de Oracle es el reemplazo moderno del esquema OE m\u00e1s antiguo. <\/p>\n\n\n\n<p>Viene con Oracle 19c, se mantiene activamente y est\u00e1 construido de la manera en que se construyen la mayor\u00eda de las aplicaciones Oracle reales hoy en d\u00eda: columnas IDENTITY en lugar de pares secuencia-disparador, JSON almacenado en columnas BLOB y vistas que utilizan funciones SQL espec\u00edficas de Oracle.<\/p>\n\n\n\n<p>Ejecut\u00e9 la migraci\u00f3n completa usando ora2pg 25.0 con Oracle 19c como origen y PostgreSQL 18 como destino. <\/p>\n\n\n\n<p>Esta publicaci\u00f3n cubre los cinco problemas que requirieron intervenci\u00f3n manual y por qu\u00e9 cada uno aparecer\u00e1 en casi todos los esquemas de producci\u00f3n que migre.<\/p>\n\n\n\n<p>Esta es la tercera publicaci\u00f3n de la serie. <\/p>\n\n\n\n<p>En <a href=\"https:\/\/rootfan.com\/es\/ejemplo-de-migracion-con-ora2pg\/\">Publicaci\u00f3n del esquema de RR. HH.<\/a> cubri\u00f3 patrones de secuencia de activaci\u00f3n, <code>%TIPO<\/code> par\u00e1metros, y el error de reaplicaci\u00f3n de FK. <\/p>\n\n\n\n<p>En <a href=\"https:\/\/rootfan.com\/es\/migracion-de-ora2pg-de-oracle-a-postgresql-paso-a-paso\/\">Publicaci\u00f3n de esquema SH<\/a> tablas particionadas cubiertas, \u00edndices de mapa de bits y vistas materializadas.<\/p>\n\n\n\n<p>CO introduce tres nuevas categor\u00edas de problemas que no se ven en ninguna de esas.<\/p>\n\n\n\n<!--more-->\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>\u00cdndice<\/h2><nav><ul><li><a href=\"#what-co-contains\">Qu\u00e9 contiene el CO<\/a><ul><li><a href=\"#problem-1-identity-columns-have-no-explicit-sequences\">Problema 1: Las columnas de identidad no tienen secuencias expl\u00edcitas<\/a><\/li><li><a href=\"#problem-2-blob-storing-json-must-become-jsonb-not-bytea\">Problema 2: Almacenar BLOB como JSON debe ser JSONB, no BYTEA<\/a><\/li><li><a href=\"#problem-3-fk-columns-are-number38-pks-are-bigint-type-mismatch\">Problema 3: Las columnas FK son NUMBER(38), las PK son bigint \u2014 Desajuste de tipos<\/a><\/li><li><a href=\"#problem-4-the-is-json-check-constraint-uses-oracle-syntax\">Problema 4: La restricci\u00f3n de verificaci\u00f3n IS JSON utiliza sintaxis de Oracle<\/a><\/li><li><a href=\"#problem-5-three-views-use-oracle-specific-sql-functions\">Problema 5: Tres vistas usan funciones SQL espec\u00edficas de Oracle<\/a><ul><li><a href=\"#customer_order_products-listagg-with-on-overflow\">customer_order_products \u2014 LISTAGG con DESBORDAMIENTO ACTIVADO<\/a><\/li><li><a href=\"#store_orders-grouping_id\">store_orders \u2014 GROUPING_ID<\/a><\/li><li><a href=\"#product_reviews-json_table\">product_reviews \u2014 JSON_TABLE<\/a><\/li><\/ul><\/li><\/ul><\/li><li><a href=\"#running-the-migration-every-command-in-order\">Ejecutando la Migraci\u00f3n: Cada Comando en Orden<\/a><ul><li><a href=\"#environment\">Medio ambiente<\/a><\/li><li><a href=\"#step-1-gather-oracle-statistics\">Paso 1 \u2014 Recopilar estad\u00edsticas de Oracle<\/a><\/li><li><a href=\"#step-2-create-the-output-directory\">Paso 2: cree el directorio de salida<\/a><\/li><li><a href=\"#step-3-base-ora2pg-conf\">Paso 3: Configurar ora2pg.conf<\/a><\/li><li><a href=\"#step-4-generate-the-assessment-report\">Paso 4: Generar el informe de evaluaci\u00f3n<\/a><\/li><li><a href=\"#step-5-analyse-column-types\">Paso 5 \u2014 Analizar tipos de columna<\/a><\/li><li><a href=\"#step-6-add-modify_type-and-re-save-the-config\">Paso 6: A\u00f1adir MODIFY_TYPE y volver a guardar la configuraci\u00f3n<\/a><\/li><li><a href=\"#step-7-run-the-schema-exports\">Paso 7: Ejecutar las exportaciones del esquema<\/a><\/li><li><a href=\"#step-8-write-the-manual-fix-files\">Paso 8 \u2014 Escribir los archivos de correcci\u00f3n manual<\/a><\/li><li><a href=\"#step-9-export-the-data\">Paso 9 \u2014 Exportar los datos<\/a><\/li><li><a href=\"#step-10-create-the-database\">Paso 10 \u2014 Crear la base de datos<\/a><\/li><li><a href=\"#step-11-load-in-dependency-order\">Paso 11 \u2014 Cargar en orden de dependencia<\/a><\/li><li><a href=\"#step-12-re-apply-fk-constraints\">Paso 12 \u2014 Vuelve a aplicar las restricciones FK<\/a><\/li><li><a href=\"#step-13-advance-identity-sequences\">Paso 13 \u2014 Avanzar las secuencias de IDENTIDAD<\/a><\/li><li><a href=\"#step-14-load-the-views\">Paso 14 \u2014 Cargar las vistas<\/a><\/li><li><a href=\"#step-15-run-the-test-comparison\">Paso 15: Ejecute la comparaci\u00f3n de PRUEBA<\/a><\/li><li><a href=\"#what-the-final-test-report-looks-like\">C\u00f3mo se ve el Informe de Prueba Final<\/a><\/li><\/ul><\/li><li><a href=\"#summary\">En resumen<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-co-contains\">Qu\u00e9 contiene el CO<\/h2>\n\n\n\n<p>En <a href=\"https:\/\/github.com\/oracle-samples\/db-sample-schemas\" rel=\"nofollow noopener\" target=\"_blank\">Esquema de CO<\/a> El esquema de referencia de Oracle para la gesti\u00f3n de pedidos en el sector minorista es: clientes, tiendas, productos, pedidos, env\u00edos, art\u00edculos de pedido e inventario.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Tipo de objeto<\/th><th>Contar<\/th><\/tr><\/thead><tbody><tr><td>Tablas<\/td><td>7<\/td><\/tr><tr><td>Vistas<\/td><td>4<\/td><\/tr><tr><td>Secuencias<\/td><td>0 (solo columnas de IDENTIDAD)<\/td><\/tr><tr><td>Procedimientos almacenados<\/td><td>0<\/td><\/tr><tr><td>Disparadores<\/td><td>0<\/td><\/tr><tr><td>Filas (total)<\/td><td>~8,800<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>La ausencia de procedimientos almacenados y disparadores mantiene el esfuerzo de conversi\u00f3n de PL\/SQL en cero. La complejidad proviene de tres puntos: c\u00f3mo Oracle maneja las columnas IDENTITY, una columna BLOB que almacena JSON y cuatro vistas, tres de las cuales utilizan funciones SQL espec\u00edficas de Oracle que PostgreSQL no soporta.<\/p>\n\n\n\n<p>ora2pg califica el esquema de CO <strong>A-3<\/strong>migraci\u00f3n directa, estimada en tres horas persona. Los impulsores de costos son las tres vistas no port\u00e1tiles.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"problem-1-identity-columns-have-no-explicit-sequences\">Problema 1: Las columnas de identidad no tienen secuencias expl\u00edcitas<\/h3>\n\n\n\n<p>Usos de CO <code>GENERADO POR DEFECTO EN NULO COMO IDENTIDAD<\/code> en cada columna de clave primaria. Oracle gestiona las secuencias subyacentes internamente \u2014 no hay <code>CREAR SECUENCIA<\/code> declaraciones en el esquema, y no hay pares de secuencia-disparador como los utilizados en el esquema HR.<\/p>\n\n\n\n<p>ora2pg convierte la sintaxis de Oracle correctamente: <code>GENERADO POR DEFECTO EN NULO COMO IDENTIDAD<\/code> se convierte <code>GENERADO POR DEFECTO COMO IDENTIDAD<\/code> en PostgreSQL. Esa parte no requiere trabajo manual.<\/p>\n\n\n\n<p>El problema surge despu\u00e9s de la carga de datos.<\/p>\n\n\n\n<p>Cuando ora2pg exporta datos mediante COPY, exporta los identificadores de fila reales de Oracle: 1, 2, 3, ... hasta el ID m\u00e1s alto. El protocolo COPY de PostgreSQL acepta esos valores y los inserta directamente en las columnas IDENTITY. La secuencia IDENTITY no se llama durante una carga COPY. Despu\u00e9s de que la carga se completa, cada secuencia IDENTITY permanece en su valor inicial de 1.<\/p>\n\n\n\n<p>La primera inserci\u00f3n en <code>clientes<\/code> despu\u00e9s de la migraci\u00f3n intentar\u00e1 usar <code>customer_id = 1<\/code>. Esa fila ya existe. La inserci\u00f3n falla con <code>la clave duplicada viola la restricci\u00f3n \u00fanica<\/code>.<\/p>\n\n\n\n<p>La soluci\u00f3n es adelantar cada secuencia de IDENTIDAD m\u00e1s all\u00e1 del valor m\u00e1s alto cargado:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSET search_path = co, public;\nSELECT setval(pg_get_serial_sequence(&#039;co.customers&#039;,  &#039;customer_id&#039;),  (SELECT MAX(customer_id)  FROM co.customers));\nSELECT setval(pg_get_serial_sequence(&#039;co.orders&#039;,     &#039;order_id&#039;),     (SELECT MAX(order_id)     FROM co.orders));\nSELECT setval(pg_get_serial_sequence(&#039;co.shipments&#039;,  &#039;shipment_id&#039;),  (SELECT MAX(shipment_id)  FROM co.shipments));\nSELECT setval(pg_get_serial_sequence(&#039;co.stores&#039;,     &#039;store_id&#039;),     (SELECT MAX(store_id)     FROM co.stores));\nSELECT setval(pg_get_serial_sequence(&#039;co.products&#039;,   &#039;product_id&#039;),   (SELECT MAX(product_id)   FROM co.products));\n<\/pre><\/div>\n\n\n<p><code>pg_get_serial_sequence<\/code> resuelve el nombre de la secuencia a partir de los nombres de tabla y columna. Esto evita codificar de forma fija los nombres de secuencia, que var\u00edan entre versiones de ora2pg.<\/p>\n\n\n\n<p>Ejecuta este bloque inmediatamente despu\u00e9s de la carga de datos, antes de que cualquier aplicaci\u00f3n toque la base de datos migrada. En un esquema de producci\u00f3n, las secuencias omitidas causan fallos en las inserciones que son f\u00e1ciles de pasar por alto en las pruebas si el conjunto de datos de prueba utiliza identificadores diferentes a los de producci\u00f3n.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"problem-2-blob-storing-json-must-become-jsonb-not-bytea\">Problema 2: Almacenar BLOB como JSON debe ser JSONB, no BYTEA<\/h3>\n\n\n\n<p><code>productos.detalles_producto<\/code> se declara como <code>BOLO<\/code> en Oracle con una <code>Comprobar (product_details ES JSON)<\/code> restricci\u00f3n. <\/p>\n\n\n\n<p>Las bases de datos Oracle anteriores a la 21c almacenan JSON como BLOB o CLOB; no hay un tipo JSON nativo.<\/p>\n\n\n\n<p>ora2pg mapea todas las columnas BLOB a <code>BYTEA<\/code> por defecto. <\/p>\n\n\n\n<p>Para <code>imagen_producto<\/code> y <code>tiendas.logotipo<\/code>, eso es correcto \u2014 almacenan datos de im\u00e1genes binarias. <\/p>\n\n\n\n<p>Para <code>detalles_del_producto<\/code>, est\u00e1 mal.<\/p>\n\n\n\n<p><code>BYTEA<\/code> en PostgreSQL almacena bytes sin procesar. No hay operadores JSON, no hay funciones JSON, no hay validaci\u00f3n en la inserci\u00f3n. El <code>rese\u00f1as de productos<\/code> ver consultas <code>detalles_del_producto<\/code> como JSON usando <code>jsonb_array_elements<\/code> despu\u00e9s de la reescritura (v\u00e9ase el Problema 5 a continuaci\u00f3n). Esa funci\u00f3n requiere un <code>JSONB<\/code> argumento \u2014 fallar\u00e1 con <code>function jsonb_array_elements(bytea) does not exist<\/code> si la columna es <code>BYTEA<\/code>.<\/p>\n\n\n\n<p>La soluci\u00f3n es un <code>MODIFICAR_TIPO<\/code> anular antes de ejecutar la exportaci\u00f3n de la TABLA:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMODIFY_TYPE   PRODUCTS:PRODUCT_DETAILS:jsonb\n<\/pre><\/div>\n\n\n<p>Esta es parte de una m\u00e1s larga <code>MODIFICAR_TIPO<\/code> l\u00ednea \u2014 ver el Paso 6 a continuaci\u00f3n para la directiva completa.<\/p>\n\n\n\n<p><code>JSONB<\/code> impone JSON v\u00e1lido en cada inserci\u00f3n autom\u00e1ticamente. El <code>Comprobar (product_details ES JSON)<\/code> La restricci\u00f3n es, por lo tanto, redundante despu\u00e9s del cambio del tipo de columna. Tambi\u00e9n utiliza sintaxis de Oracle; PostgreSQL no tiene <code>es JSON<\/code> predicado \u2014 por lo tanto, debe eliminarse del DDL exportado antes de la carga. Ver Problema 4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"problem-3-fk-columns-are-number38-pks-are-bigint-type-mismatch\">Problema 3: Las columnas FK son NUMBER(38), las PK son bigint \u2014 Desajuste de tipos<\/h3>\n\n\n\n<p><code>FORCE_IDENTITY_BIGINT 1<\/code> cAuses ora2pg a exportar las columnas de clave primaria de IDENTIDAD como <code>entero largo<\/code>. <code>PG_INTEGER_TYPE 1<\/code> convierte desnudo <code>N\u00daMERO<\/code> columnas a <code>entero largo<\/code>.<\/p>\n\n\n\n<p>Las columnas FK en CO \u2014 <code>\u00f3rdenes.cliente_id<\/code>, <code>\u00f3rdenes.tienda_id<\/code>, <code>order_items.order_id<\/code>, y otros \u2014 se declaran como <code>N\u00daMERO(38)<\/code> en Oracle. Esa es la representaci\u00f3n interna de Oracle de una columna de enteros declarada sin precisi\u00f3n. Debido a que la precisi\u00f3n es expl\u00edcitamente <code>38<\/code>, <code>PG_INTEGER_TYPE 1<\/code> no aplica. ora2pg los mapea a <code>num\u00e9rico(38)<\/code>.<\/p>\n\n\n\n<p>El resultado: las columnas de clave primaria son <code>entero largo<\/code>, las columnas de clave externa que hacen referencia a ellas son <code>num\u00e9rico(38)<\/code>. PostgreSQL requiere que las columnas de FK y PK tengan el mismo tipo. La carga del DDL tiene \u00e9xito, pero la creaci\u00f3n de las restricciones FK falla:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nERROR:  foreign key constraint &quot;orders_customer_id_fk&quot; cannot be implemented\nDETAIL:  Key columns &quot;customer_id&quot; and &quot;customer_id&quot; are of incompatible types: numeric and bigint.\n<\/pre><\/div>\n\n\n<p>La soluci\u00f3n es a\u00f1adir todas las columnas FK y otras columnas enteras a <code>MODIFICAR_TIPO<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMODIFY_TYPE   INVENTORY:STORE_ID:bigint,INVENTORY:PRODUCT_ID:bigint,INVENTORY:PRODUCT_INVENTORY:integer,ORDERS:CUSTOMER_ID:bigint,ORDERS:STORE_ID:bigint,ORDER_ITEMS:ORDER_ID:bigint,ORDER_ITEMS:LINE_ITEM_ID:integer,ORDER_ITEMS:PRODUCT_ID:bigint,ORDER_ITEMS:QUANTITY:integer,ORDER_ITEMS:SHIPMENT_ID:bigint,SHIPMENTS:STORE_ID:bigint,SHIPMENTS:CUSTOMER_ID:bigint\n<\/pre><\/div>\n\n\n<p><code>MODIFICAR_TIPO<\/code> lee solo la primera l\u00ednea de la directiva. Todas las anulaciones, incluida la anulaci\u00f3n JSONB del Problema 2 y la <code>num\u00e9rico<\/code> anulaciones desde abajo \u2014 deben estar en una sola l\u00ednea separada por comas.<\/p>\n\n\n\n<p>Tampoco: no incluir precisi\u00f3n de tipo dentro <code>MODIFICAR_TIPO<\/code> escribir <code>num\u00e9rico<\/code>, no <code>num\u00e9rico(10,2)<\/code>).<\/p>\n\n\n\n<p>La coma dentro de los par\u00e9ntesis se trata como un delimitador y rompe el an\u00e1lisis.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"problem-4-the-is-json-check-constraint-uses-oracle-syntax\">Problema 4: La restricci\u00f3n de verificaci\u00f3n IS JSON utiliza sintaxis de Oracle<\/h3>\n\n\n\n<p>ora2pg exporta el <code>productos_json_c<\/code> restricci\u00f3n como:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCONSTRAINT products_json_c CHECK (product_details IS JSON)\n<\/pre><\/div>\n\n\n<p>PostgreSQL no tiene <code>es JSON<\/code> predicado. La carga de la DDL de la tabla falla inmediatamente con un error de sintaxis.<\/p>\n\n\n\n<p>La restricci\u00f3n tambi\u00e9n es redundante. <code>JSONB<\/code> en PostgreSQL valida el JSON en cada inserci\u00f3n. Cualquier fila que falle la validaci\u00f3n JSON es rechazada antes de llegar al almacenamiento. El <code>es JSON<\/code> La restricci\u00f3n no hace nada que el tipo de columna ya no haga.<\/p>\n\n\n\n<p>La soluci\u00f3n: elimina la l\u00ednea de restricci\u00f3n del DDL exportado antes de cargarlo.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsed -i &#039;\/products_json_c\/d&#039; \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql\n<\/pre><\/div>\n\n\n<p>Verificar<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ngrep &#039;products_json_c&#039; \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql\n# Expected: no output\n<\/pre><\/div>\n\n\n<p>El informe TEST mostrar\u00e1 una DIFERENCIA DE COMPROBACI\u00d3N DE RESTRICCIONES para el <code>productos<\/code> tabla \u2014 una restricci\u00f3n en Oracle, cero en PostgreSQL. Esto es esperado y correcto.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"problem-5-three-views-use-oracle-specific-sql-functions\">Problema 5: Tres vistas usan funciones SQL espec\u00edficas de Oracle<\/h3>\n\n\n\n<p>El CO tiene cuatro vistas. Una (<code>pedidos_productos<\/code>) usa SQL est\u00e1ndar y se convierte sin cambios. Tres usan funciones que no tienen un equivalente directo en PostgreSQL:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"customer_order_products-listagg-with-on-overflow\"><code>productos_pedido_cliente<\/code> \u2014 LISTAGG con ON OVERFLOW<\/h4>\n\n\n\n<p>Oracle <code>LISTAGG(expr, separador ON OVERFLOW TRUNCATE '...' WITH COUNT)<\/code> concatena valores en una cadena delimitada con manejo de desbordamiento. <\/p>\n\n\n\n<p>PostgreSQL <code>STRING_AGG(expr, separador ORDEN POR ...)<\/code> es la opci\u00f3n equivalente \u2014 sin desbordamiento.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n-- Oracle\nLISTAGG(p.product_name, &#039;, &#039; ON OVERFLOW TRUNCATE &#039;...&#039; WITH COUNT)\n  WITHIN GROUP (ORDER BY oi.line_item_id) items\n\n-- PostgreSQL\nSTRING_AGG(p.product_name, &#039;, &#039; ORDER BY oi.line_item_id) items\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"store_orders-grouping_id\"><code>pedidos_almacen<\/code> \u2014 GROUPING_ID<\/h4>\n\n\n\n<p>Oracle <code>GROUPING_ID(col1, col2)<\/code> devuelve un vector de bits entero que codifica qu\u00e9 columnas se agregan en un <code>GROUPING SETS<\/code> b\u00fasqueda. <\/p>\n\n\n\n<p>PostgreSQL <code>AGRUPAR POR(col1, col2)<\/code> hace exactamente lo mismo \u2014 el nombre de la funci\u00f3n difiere, la sem\u00e1ntica es id\u00e9ntica. <\/p>\n\n\n\n<p>El reemplazo es uno por uno.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n-- Oracle\nCASE grouping_id(store_name, order_status)\n  WHEN 1 THEN &#039;STORE TOTAL&#039;\n  ...\n\n-- PostgreSQL\nCASE grouping(s.store_name, o.order_status)\n  WHEN 1 THEN &#039;STORE TOTAL&#039;\n  ...\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"product_reviews-json_table\"><code>rese\u00f1as de productos<\/code> \u2014 TABLA_JSON<\/h4>\n\n\n\n<p>Oracle <code>JSON_TABLE<\/code> expande un arreglo JSON en filas usando una proyecci\u00f3n relacional.<\/p>\n\n\n\n<p>PostgreSQL no tiene <code>JSON_TABLE<\/code> equivalente antes de la versi\u00f3n 15 (se a\u00f1adi\u00f3 en PostgreSQL 15 como parte del est\u00e1ndar SQL\/JSON, pero con una sintaxis diferente). <\/p>\n\n\n\n<p>Para PostgreSQL 14 y versiones anteriores, o para un comportamiento consistente entre versiones, reescribe usando <code>jsonb_array_elements<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n-- Oracle\nFROM products p,\n     JSON_TABLE(p.product_details, &#039;$&#039;\n       COLUMNS (NESTED PATH &#039;$.reviews&#x5B;*]&#039;\n         COLUMNS (rating INTEGER PATH &#039;$.rating&#039;,\n                  review VARCHAR2(4000) PATH &#039;$.review&#039;))) r\n\n-- PostgreSQL\nFROM products p,\n     jsonb_array_elements(p.product_details-&gt;&#039;reviews&#039;) AS review_row\n<\/pre><\/div>\n\n\n<p>En la versi\u00f3n de PostgreSQL, cada elemento de matriz JSON se expone como un <code>jsonb<\/code> valor llamado <code>fila_revision<\/code>. <\/p>\n\n\n\n<p>Los valores de las columnas se extraen con el <code>->><\/code> operador <code>Calificaci\u00f3n de review_row'<\/code> y <code>review_row-&gt;&gt;'review'<\/code>. <\/p>\n\n\n\n<p>El elenco <code>::ENTERO<\/code> el campo de calificaci\u00f3n es obligatorio porque <code>->><\/code> siempre regresa <code>texto<\/code>.<\/p>\n\n\n\n<p>Esta reescritura depende de <code>detalles_del_producto<\/code> ser <code>JSONB<\/code> \u2014 si la columna es <code>BYTEA<\/code> (El problema 2 no se solucion\u00f3), la vista falla inmediatamente.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"running-the-migration-every-command-in-order\">Ejecutando la Migraci\u00f3n: Cada Comando en Orden<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"environment\">Medio ambiente<\/h3>\n\n\n\n<p>Dos m\u00e1quinas virtuales en la misma red. <code>srv1<\/code> (192.168.0.180) ejecuta Oracle 19c con el esquema CO en PDB <code>pdb1<\/code>. <code>srv2<\/code> (192.168.0.181) ejecuta Ubuntu con PostgreSQL 18 y ora2pg instalado. Todos los comandos a continuaci\u00f3n se ejecutan en <code>srv2<\/code> a menos que se indique lo contrario.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-1-gather-oracle-statistics\">Paso 1 \u2014 Recopilar estad\u00edsticas de Oracle<\/h3>\n\n\n\n<p>Correr sobre <code>srv1<\/code> antes de generar el informe. las estimaciones de esfuerzo de ora2pg utilizan estad\u00edsticas almacenadas de Oracle \u2014 las estad\u00edsticas obsoletas producen recuentos inexactos.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n-- On Oracle (srv1)\nBEGIN\n  DBMS_STATS.GATHER_SCHEMA_STATS(&#039;CO&#039;);\n  DBMS_STATS.GATHER_DICTIONARY_STATS;\nEND;\n\/\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-2-create-the-output-directory\">Paso 2: cree el directorio de salida<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nmkdir -p \/home\/fernando\/ora2pg-co\/output\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-3-base-ora2pg-conf\">Paso 3: Configurar ora2pg.conf<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n# \/etc\/ora2pg\/ora2pg.conf\nORACLE_DSN    dbi:Oracle:host=192.168.0.180;service_name=pdb1;port=1521\nORACLE_USER   system\nORACLE_PWD    &lt;system password&gt;\nSCHEMA        CO\nEXPORT_SCHEMA 1\nCREATE_SCHEMA 1\nOUTPUT_DIR    \/home\/fernando\/ora2pg-co\/output\n<\/pre><\/div>\n\n\n<p>Utilice <code>sistema<\/code>, no <code>co<\/code> \u2014 la exportaci\u00f3n de COPIA dice <code>v$base de datos<\/code>, que requiere privilegios de DBA.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-4-generate-the-assessment-report\">Paso 4: Generar el informe de evaluaci\u00f3n<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nora2pg -t SHOW_REPORT --estimate_cost --dump_as_html \\\n  &gt; \/home\/fernando\/ora2pg-co\/output\/report-co.html\n<\/pre><\/div>\n\n\n<p>Abrir el HTML en un navegador. CO deber\u00eda anotar <strong>A-3<\/strong>. Los impulsores de costos son las tres vistas no port\u00e1tiles.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-5-analyse-column-types\">Paso 5 \u2014 Analizar tipos de columna<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nora2pg -t SHOW_COLUMN &gt; \/home\/fernando\/ora2pg-co\/output\/columns-co.txt\n<\/pre><\/div>\n\n\n<p>Columnas clave para revisar:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Columna<\/th><th>ora2pg predeterminado<\/th><th>Tipo correcto<\/th><th>Raz\u00f3n<\/th><\/tr><\/thead><tbody><tr><td><code>PRODUCTOS.PRECIO_UNITARIO<\/code><\/td><td><code>doble precisi\u00f3n<\/code><\/td><td><code>num\u00e9rico<\/code><\/td><td>Monetario: los n\u00fameros de punto flotante causan errores de redondeo<\/td><\/tr><tr><td><code>PRECIO_UNITARIO_PEDIDO<\/code><\/td><td><code>doble precisi\u00f3n<\/code><\/td><td><code>num\u00e9rico<\/code><\/td><td>Mismo<\/td><\/tr><tr><td><code>PRODUCTOS.DETALLES_DEL_PRODUCTO<\/code><\/td><td><code>bytea<\/code><\/td><td><code>jsonb<\/code><\/td><td>Tiendas JSON<\/td><\/tr><tr><td><code>ORDERS.CUSTOMER_ID<\/code><\/td><td><code>num\u00e9rico(38)<\/code><\/td><td><code>entero largo<\/code><\/td><td>FK a <code>entero largo<\/code> PK \u2014 tipo incorrecto<\/td><\/tr><tr><td>Todos los dem\u00e1s <code>N\u00daMERO(38)<\/code> Columnas FK\/entero<\/td><td><code>num\u00e9rico(38)<\/code><\/td><td><code>entero largo<\/code> o <code>entero<\/code><\/td><td>La misma raz\u00f3n<\/td><\/tr><tr><td><code>TIENDAS.LATITUD<\/code>, <code>ALMACENES.LONGITUD<\/code><\/td><td><code>doble precisi\u00f3n<\/code><\/td><td><code>doble precisi\u00f3n<\/code><\/td><td>Coordenadas geogr\u00e1ficas \u2014 el tipo flotante es correcto<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-6-add-modify_type-and-re-save-the-config\">Paso 6: A\u00f1adir MODIFY_TYPE y volver a guardar la configuraci\u00f3n<\/h3>\n\n\n\n<p>Todas las anulaci\u00f3n en una sola l\u00ednea \u2014 <code>MODIFICAR_TIPO<\/code> ignora todo despu\u00e9s de la primera l\u00ednea. <\/p>\n\n\n\n<p>No uses precisi\u00f3n de tipo (escribe <code>num\u00e9rico<\/code>, no <code>num\u00e9rico(10,2)<\/code>).<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMODIFY_TYPE   PRODUCTS:PRODUCT_DETAILS:jsonb,PRODUCTS:UNIT_PRICE:numeric,ORDER_ITEMS:UNIT_PRICE:numeric,INVENTORY:STORE_ID:bigint,INVENTORY:PRODUCT_ID:bigint,INVENTORY:PRODUCT_INVENTORY:integer,ORDERS:CUSTOMER_ID:bigint,ORDERS:STORE_ID:bigint,ORDER_ITEMS:ORDER_ID:bigint,ORDER_ITEMS:LINE_ITEM_ID:integer,ORDER_ITEMS:PRODUCT_ID:bigint,ORDER_ITEMS:QUANTITY:integer,ORDER_ITEMS:SHIPMENT_ID:bigint,SHIPMENTS:STORE_ID:bigint,SHIPMENTS:CUSTOMER_ID:bigint\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-7-run-the-schema-exports\">Paso 7: Ejecutar las exportaciones del esquema<\/h3>\n\n\n\n<p>CO no tiene secuencias expl\u00edcitas ni procedimientos almacenados o desencadenadores. <\/p>\n\n\n\n<p>Solo se necesitan exportaciones de TABLAS y VISTAS.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nora2pg -t TABLE -o CO_tables.sql 2&gt;&amp;1 | tee \/home\/fernando\/ora2pg-co\/output\/table-export-co.log\nora2pg -t VIEW  -o CO_views.sql  2&gt;&amp;1 | tee \/home\/fernando\/ora2pg-co\/output\/view-export-co.log\n<\/pre><\/div>\n\n\n<p>Despu\u00e9s de la exportaci\u00f3n de la TABLA, verifique las columnas cr\u00edticas:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ngrep -E &#039;product_details|UNIT_PRICE|IDENTITY&#039; \/home\/fernando\/ora2pg-co\/output\/CO_tables.sql\n<\/pre><\/div>\n\n\n<p><code>detalles_del_producto<\/code> debe mostrar <code>JSONB<\/code>. Ambos <code>PRECIO POR UNIDAD<\/code> las columnas deben mostrar <code>NUM\u00c9RICO<\/code>. Las columnas de IDENTIDAD deben mostrar <code>GENERADO POR DEFECTO COMO IDENTIDAD<\/code>. <\/p>\n\n\n\n<p>Si alguna columna muestra el tipo incorrecto, la <code>MODIFICAR_TIPO<\/code> la directiva no surti\u00f3 efecto. Comprueba la configuraci\u00f3n.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-8-write-the-manual-fix-files\">Paso 8 \u2014 Escribir los archivos de correcci\u00f3n manual<\/h3>\n\n\n\n<p>Dos archivos de correcci\u00f3n no se pueden generar a partir de la salida de ora2pg.<\/p>\n\n\n\n<p><code>CO_tables_fixed.sql<\/code> \u2014 elimina la restricci\u00f3n IS JSON:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncp \/home\/fernando\/ora2pg-co\/output\/CO_tables.sql \\\n   \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql\nsed -i &#039;\/products_json_c\/d&#039; \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql\n<\/pre><\/div>\n\n\n<p><code>CO_views_fixed.sql<\/code> \u2014 reescribe las tres vistas espec\u00edficas de Oracle:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSET search_path = co,public;\n\n-- product_orders: standard SQL, no changes needed\nCREATE OR REPLACE VIEW product_orders AS\n  SELECT p.product_name, o.order_status,\n         SUM(oi.quantity * oi.unit_price) total_sales,\n         COUNT(*) order_count\n  FROM   orders o\n  JOIN   order_items oi ON o.order_id = oi.order_id\n  JOIN   customers c    ON o.customer_id = c.customer_id\n  JOIN   products p     ON oi.product_id = p.product_id\n  GROUP  BY p.product_name, o.order_status;\n\n-- customer_order_products: LISTAGG \u2192 STRING_AGG\nCREATE OR REPLACE VIEW customer_order_products AS\n  SELECT o.order_id, o.order_tms, o.order_status,\n         c.customer_id, c.email_address, c.full_name,\n         SUM(oi.quantity * oi.unit_price) order_total,\n         STRING_AGG(p.product_name, &#039;, &#039; ORDER BY oi.line_item_id) items\n  FROM   orders o\n  JOIN   order_items oi ON o.order_id = oi.order_id\n  JOIN   customers c    ON o.customer_id = c.customer_id\n  JOIN   products p     ON oi.product_id = p.product_id\n  GROUP  BY o.order_id, o.order_tms, o.order_status,\n            c.customer_id, c.email_address, c.full_name;\n\n-- store_orders: GROUPING_ID() \u2192 GROUPING()\nCREATE OR REPLACE VIEW store_orders AS\n  SELECT CASE grouping(s.store_name, o.order_status)\n           WHEN 1 THEN &#039;STORE TOTAL&#039;\n           WHEN 2 THEN &#039;STATUS TOTAL&#039;\n           WHEN 3 THEN &#039;GRAND TOTAL&#039;\n         END total,\n         s.store_name,\n         COALESCE(s.web_address, s.physical_address) address,\n         s.latitude, s.longitude,\n         o.order_status,\n         COUNT(DISTINCT o.order_id) order_count,\n         SUM(oi.quantity * oi.unit_price) total_sales\n  FROM   stores s\n  JOIN   orders o    ON s.store_id = o.store_id\n  JOIN   order_items oi ON o.order_id = oi.order_id\n  GROUP  BY GROUPING SETS (\n    (s.store_name, COALESCE(s.web_address, s.physical_address), s.latitude, s.longitude),\n    (s.store_name, COALESCE(s.web_address, s.physical_address), s.latitude, s.longitude, o.order_status),\n    o.order_status,\n    ()\n  );\n\n-- product_reviews: JSON_TABLE \u2192 jsonb_array_elements\nCREATE OR REPLACE VIEW product_reviews AS\n  SELECT p.product_name,\n         (review_row-&gt;&gt;&#039;rating&#039;)::INTEGER AS rating,\n         ROUND(\n           AVG((review_row-&gt;&gt;&#039;rating&#039;)::INTEGER)\n             OVER (PARTITION BY p.product_name),\n           2\n         ) avg_rating,\n         review_row-&gt;&gt;&#039;review&#039; AS review\n  FROM   products p,\n         jsonb_array_elements(p.product_details-&gt;&#039;reviews&#039;) AS review_row;\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-9-export-the-data\">Paso 9 \u2014 Exportar los datos<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nora2pg -t COPY -o CO_data.sql 2&gt;&amp;1 | tee \/home\/fernando\/ora2pg-co\/output\/copy-export-co.log\n<\/pre><\/div>\n\n\n<p>Despu\u00e9s de la exportaci\u00f3n, compruebe si hay saltos de l\u00ednea incrustados en los datos JSON. ora2pg no escapa los caracteres literales de salto de l\u00ednea dentro de los valores de cadena JSON. <\/p>\n\n\n\n<p>Si alguno <code>detalles_del_producto<\/code> el valor contiene un salto de l\u00ednea real, el analizador COPY lo trata como un separador de filas y falla con <code>Sintaxis de entrada no v\u00e1lida para el tipo json<\/code>.<\/p>\n\n\n\n<p>Arreglar saltos de l\u00ednea incrustados antes de cargar:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npython3 &lt;&lt; &#039;EOF&#039;\nimport re\n\nwith open(&#039;\/home\/fernando\/ora2pg-co\/output\/CO_data.sql&#039;, &#039;r&#039;) as f:\n    lines = f.read().split(&#039;\\n&#039;)\n\nresult = &#x5B;]\nin_products = False\npending = None\n\nfor line in lines:\n    if re.match(r&#039;COPY products\\b&#039;, line):\n        in_products = True\n        result.append(line)\n        continue\n    if in_products:\n        if line == &#039;\\\\.&#039;:\n            if pending is not None:\n                result.append(pending)\n                pending = None\n            result.append(line)\n            in_products = False\n            continue\n        if re.match(r&#039;^\\d+\\t&#039;, line):\n            if pending is not None:\n                result.append(pending)\n            pending = line\n        else:\n            pending = (pending + &#039;\\\\n&#039; + line) if pending else line\n    else:\n        result.append(line)\n\nwith open(&#039;\/home\/fernando\/ora2pg-co\/output\/CO_data_fixed.sql&#039;, &#039;w&#039;) as f:\n    f.write(&#039;\\n&#039;.join(result))\nprint(&quot;Done&quot;)\nEOF\n<\/pre><\/div>\n\n\n<p>Verifica que el recuento de filas sea correcto:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ngrep -c $&#039;\\t&#039; \/home\/fernando\/ora2pg-co\/output\/CO_data_fixed.sql\n# Expected: 8783\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-10-create-the-database\">Paso 10 \u2014 Crear la base de datos<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsudo -u postgres psql -c &quot;CREATE ROLE co WITH LOGIN PASSWORD &#039;co&#039;;&quot;\nsudo -u postgres psql -c &quot;CREATE DATABASE codb OWNER co;&quot;\nPGPASSWORD=co psql -U co -d codb -h localhost -c &quot;CREATE SCHEMA co;&quot;\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-11-load-in-dependency-order\">Paso 11 \u2014 Cargar en orden de dependencia<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n# Tables first\nPGPASSWORD=co psql -U co -d codb -h localhost \\\n  -f \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql\n\n# Data \u2014 FKs are dropped inside the file before load, not re-added after\nPGPASSWORD=co psql -U co -d codb -h localhost \\\n  -f \/home\/fernando\/ora2pg-co\/output\/CO_data_fixed.sql\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-12-re-apply-fk-constraints\">Paso 12 \u2014 Vuelve a aplicar las restricciones FK<\/h3>\n\n\n\n<p>COPY file de ora2pg elimina todas las restricciones de clave externa antes de la carga de datos y nunca las vuelve a agregar.<\/p>\n\n\n\n<p>Este es el mismo error que en el laboratorio de RR. HH. (<a href=\"https:\/\/github.com\/darold\/ora2pg\/issues\" rel=\"nofollow noopener\" target=\"_blank\">problema #1960<\/a>).<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n(echo &quot;SET search_path TO co;&quot;; \\\n grep &#039;ADD CONSTRAINT.*FOREIGN KEY&#039; \\\n   \/home\/fernando\/ora2pg-co\/output\/CO_tables_fixed.sql) | \\\n  PGPASSWORD=co psql -U co -d codb -h localhost\n<\/pre><\/div>\n\n\n<p>Verifica el conteo:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nPGPASSWORD=co psql -U co -d codb -h localhost -c &quot;\nSELECT COUNT(*) FROM information_schema.table_constraints\nWHERE constraint_schema = &#039;co&#039; AND constraint_type = &#039;FOREIGN KEY&#039;;&quot;\n# Expected: 9\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-13-advance-identity-sequences\">Paso 13 \u2014 Avanzar las secuencias de IDENTIDAD<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nPGPASSWORD=co psql -U co -d codb -h localhost &lt;&lt; &#039;EOF&#039;\nSET search_path = co, public;\nSELECT setval(pg_get_serial_sequence(&#039;co.customers&#039;,  &#039;customer_id&#039;),  (SELECT MAX(customer_id)  FROM co.customers));\nSELECT setval(pg_get_serial_sequence(&#039;co.orders&#039;,     &#039;order_id&#039;),     (SELECT MAX(order_id)     FROM co.orders));\nSELECT setval(pg_get_serial_sequence(&#039;co.shipments&#039;,  &#039;shipment_id&#039;),  (SELECT MAX(shipment_id)  FROM co.shipments));\nSELECT setval(pg_get_serial_sequence(&#039;co.stores&#039;,     &#039;store_id&#039;),     (SELECT MAX(store_id)     FROM co.stores));\nSELECT setval(pg_get_serial_sequence(&#039;co.products&#039;,   &#039;product_id&#039;),   (SELECT MAX(product_id)   FROM co.products));\nEOF\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-14-load-the-views\">Paso 14 \u2014 Cargar las vistas<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nPGPASSWORD=co psql -U co -d codb -h localhost \\\n  -f \/home\/fernando\/ora2pg-co\/output\/CO_views_fixed.sql\n# Expected: CREATE VIEW \u00d7 4 \u2014 no errors\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"step-15-run-the-test-comparison\">Paso 15: Ejecute la comparaci\u00f3n de PRUEBA<\/h3>\n\n\n\n<p>A\u00f1adir conexi\u00f3n a PostgreSQL <code>ora2pg.conf<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nPG_DSN    dbi:Pg:dbname=codb;host=localhost;port=5432\nPG_USER   co\nPG_PWD    co\n<\/pre><\/div>\n\n<div class=\"wp-block-syntaxhighlighter-code\" data-no-translation=\"\"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nora2pg -t TEST 2&gt;&amp;1 | tee \/home\/fernando\/ora2pg-co\/output\/CO_test.txt\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"what-the-final-test-report-looks-like\">C\u00f3mo se ve el Informe de Prueba Final<\/h3>\n\n\n\n<p>Despu\u00e9s de aplicar las cinco correcciones, <code>ora2pg -t TEST<\/code> deber\u00eda mostrar UNA DIFERENCIA y todo lo dem\u00e1s BIEN.<\/p>\n\n\n\n<p><strong>VERIFICAR RESTRICCIONES DIFERENCIA en <code>productos<\/code><\/strong> \u2014 Oracle tiene una restricci\u00f3n CHECK (<code>productos_json_c<\/code>), PostgreSQL tiene cero. <\/p>\n\n\n\n<p>Esto es esperado: la restricci\u00f3n fue eliminada intencionalmente porque usa sintaxis de Oracle y es redundante con <code>JSONB<\/code> Validaci\u00f3n de tipo de columna.<\/p>\n\n\n\n<p>Cada dos secciones \u2014columnas, \u00edndices, PKs, FKs, tablas, vistas, secuencias, recuentos de filas\u2014 deber\u00edan mostrar OK.<\/p>\n\n\n\n<p>Cualquier otra l\u00ednea DIFF es un problema real que debe resolverse antes del corte.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"summary\">En resumen<\/h2>\n\n\n\n<p>CO es una migraci\u00f3n m\u00e1s limpia que HR o SH en algunos aspectos: sin procedimientos almacenados, sin disparadores, sin \u00edndices de mapa de bits, sin tablas particionadas. Los problemas que introduce son de car\u00e1cter diferente.<\/p>\n\n\n\n<p>Las secuencias de identidad fallan despu\u00e9s de una carga de datos, lo cual es invisible hasta la primera inserci\u00f3n en producci\u00f3n; no hay ninguna advertencia durante la migraci\u00f3n misma. <code>establecer valor<\/code> el paso es f\u00e1cil de pasar por alto porque la carga tiene \u00e9xito limpiamente sin \u00e9l.<\/p>\n\n\n\n<p>El patr\u00f3n BLOB-as-JSON es com\u00fan en bases de datos Oracle creadas antes de la versi\u00f3n 21c, donde no exist\u00eda un tipo JSON nativo. Cada esquema de Oracle que almacena JSON necesita la misma anulaci\u00f3n de MODIFY_TYPE y la misma eliminaci\u00f3n de la restricci\u00f3n IS JSON. Las reescrituras de vistas son un trabajo manual \u00fanico, pero las <code>Agrupar cadenas<\/code>, <code>AGRUPACI\u00d3N<\/code>y <code>jsonb_array_elements<\/code> Las sustituciones son patrones que volver\u00e1s a ver en cualquier esquema de Oracle que tenga vistas anal\u00edticas o de consulta JSON.<\/p>\n\n\n\n<p>El tipo FK de desajuste de <code>N\u00daMERO(38)<\/code> Las columnas son un problema sistem\u00e1tico. <code>PG_INTEGER_TYPE 1<\/code> manejas desnudo <code>N\u00daMERO<\/code> columnas correctamente, pero cualquier cosa declarada con precisi\u00f3n \u2014 incluso <code>N\u00daMERO(38)<\/code>, que es como Oracle representa un entero simple en su diccionario de datos \u2014 queda fuera de la regla. En un esquema de producci\u00f3n, la salida de SHOW_COLUMN contendr\u00e1 muchas columnas de este tipo. Cada una requiere una entrada MODIFY_TYPE antes de la exportaci\u00f3n de la tabla.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><em>Si usted est\u00e1 planeando una migraci\u00f3n de Oracle a PostgreSQL y desea una evaluaci\u00f3n independiente de la complejidad, el esfuerzo y el riesgo antes de comprometerse a un cronograma, <a href=\"https:\/\/rootfan.com\/es\/servicios\/\">Ofrezco una auditor\u00eda de migraci\u00f3n a precio fijo<\/a> que produce exactamente eso.<\/em><\/p>","protected":false},"excerpt":{"rendered":"<p>El esquema CO (Customer Orders) de Oracle es el reemplazo moderno del esquema OE anterior. Viene con Oracle 19c, se mantiene activamente y se construye de la manera en que se construyen la mayor\u00eda de las aplicaciones Oracle reales hoy en d\u00eda: columnas IDENTITY en lugar de pares secuencia-disparador, JSON almacenado en columnas BLOB y vistas que utilizan funciones SQL espec\u00edficas de Oracle. Yo... <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/rootfan.com\/es\/oracle-to-postgres-migration-issues-and-fixes\/\" class=\"more-link\">Seguir leyendo<span class=\"screen-reader-text\"> \u201cMigraci\u00f3n de Oracle a Postgres: Problemas y Soluciones del Esquema CO\u201d<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":6772,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_focus_keyword":"oracle to postgres migration issues","rank_math_title":"","rank_math_description":"Oracle to PostgreSQL migration issues and fixes for the CO schema: IDENTITY sequences, BLOB-to-JSONB conversion, NUMBER(38) FK type mismatches, IS JSON constraint removal, and Oracle view rewrites.","rank_math_robots":"","rank_math_og_title":"","rank_math_og_description":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[146],"tags":[155,143,141,157,156,137,147],"class_list":["post-6754","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle-to-postgresql","tag-co-schema","tag-data-migration","tag-data-types","tag-identity-columns","tag-jsonb","tag-migration","tag-ora2pg"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/rootfan.com\/wp-content\/uploads\/6151061591_1726931f23_b-1.jpg?fit=1024%2C683&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/comments?post=6754"}],"version-history":[{"count":9,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6754\/revisions"}],"predecessor-version":[{"id":6777,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6754\/revisions\/6777"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/media\/6772"}],"wp:attachment":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/media?parent=6754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/categories?post=6754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/tags?post=6754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}