vistas vista varias una tablas pasar parametros multiples filas ejemplos ejemplo datos crear convertir con columnas sql-server oracle

sql-server - vista - pivot multiples columnas sql server



Oracle considera que las cadenas vacías son NULL mientras que SQL Server no. ¿Cómo se maneja mejor? (11)

Tengo que escribir un componente que vuelva a crear las tablas de SQL Server (estructura y datos) en una base de datos Oracle. Este componente también debe tomar nuevos datos ingresados ​​en la base de datos Oracle y copiarlos de nuevo en SQL Server.

Traducir los tipos de datos de SQL Server a Oracle no es un problema. Sin embargo, una diferencia fundamental entre Oracle y SQL Server está causando un gran dolor de cabeza. SQL Server considera que una cadena en blanco ("") es diferente de un valor NULL , por lo que una columna char se puede definir como NOT NULL y aún así incluir cadenas en blanco en los datos.

Oracle considera que una cadena en blanco es lo mismo que un valor NULL , por lo que si una columna char se define como NOT NULL , no puede insertar una cadena en blanco. Esto hace que mi componente se rompa siempre que una columna de carácter NOT NULL contenga una cadena en blanco en los datos originales de SQL Server.

Hasta ahora, mi solución ha sido no usar NOT NULL en ninguna de mis definiciones de tablas espejo de Oracle, pero necesito una solución más robusta. Esto tiene que ser una solución de código, por lo que la respuesta no puede ser "usar el producto de tal y como SQL2Oracle".

Como resolverías este problema?

Editar: esta es la única solución que he encontrado hasta ahora, y puede ayudar a ilustrar el problema. Como Oracle no permite "" en una columna NOT NULL, mi componente podría interceptar cualquier valor proveniente de SQL Server y reemplazarlo por "@" (solo por ejemplo).

Cuando agrego un nuevo registro a mi tabla Oracle, mi código tiene que escribir "@" si realmente quiero insertar un "", y cuando mi código copia la nueva fila a SQL Server, tiene que interceptar la "@" y en su lugar escriba "".

Espero que haya una manera más elegante.

Edición 2: ¿Es posible que haya una solución más simple, como alguna configuración en Oracle que consiga tratar cadenas en blanco igual que todas las otras bases de datos importantes? ¿Y esta configuración también estaría disponible en Oracle Lite?


¿Tiene que permitir cadenas vacías en el sistema SQL Server? Si puede agregar una restricción al sistema SQL Server que no permite cadenas vacías, esa es probablemente la solución más fácil.


Aunque, en su mayor parte, estoy de acuerdo con la mayoría de las otras respuestas (no voy a entrar en una discusión sobre cualquier cosa con la que no estoy de acuerdo, no el lugar para eso :))

Me doy cuenta de que OP mencionó lo siguiente:

"Oracle considera que una cadena en blanco es igual a un valor NULO, por lo que si una columna char se define como NOT NULL, no puede insertar una cadena en blanco".

Llamando específicamente CHAR, y no VARCHAR2. Por lo tanto, hablar de una "cadena vacía" de longitud 0 (es decir, '''') es discutible. Si ha declarado el CHAR como, por ejemplo, CHAR (5), entonces simplemente agrega un espacio a la cadena vacía entrante, Oracle lo va a rellenar de todos modos. Terminarás con una cadena de 5 espacios.

Ahora, si OP significa VARCHAR2, bueno, sí, es una bestia completamente distinta, y sí, la diferencia entre cadena vacía y NULL se vuelve relevante.

SQL> drop table junk; Table dropped. SQL> SQL> create table junk ( c1 char(5) not null ); Table created. SQL> SQL> insert into junk values ( ''hi'' ); 1 row created. SQL> SQL> insert into junk values ( '' '' ); 1 row created. SQL> SQL> insert into junk values ( '''' ); insert into junk values ( '''' ) * ERROR at line 1: ORA-01400: cannot insert NULL into ("GREGS"."JUNK"."C1") SQL> SQL> insert into junk values ( rpad('''', 5, '' '') ); insert into junk values ( rpad('''', 5, '' '') ) * ERROR at line 1: ORA-01400: cannot insert NULL into ("GREGS"."JUNK"."C1") SQL> SQL> declare 2 lv_in varchar2(5) := ''''; 3 begin 4 insert into junk values ( rpad(lv_in||'' '', 5) ); 5 end; 6 / PL/SQL procedure successfully completed. SQL>


Bueno, el punto principal que consideraría es la ausencia de tareas cuando algún campo puede ser nulo, el mismo campo puede ser una cadena vacía y la lógica de negocios requiere distinguir estos valores. Entonces haría esta lógica:

  • compruebe MSSQL si la columna tiene restricción NOT NULL
  • compruebe MSSQL si la columna tiene CHECK (columna <> '''') o restricción similar

Si ambos son verdaderos, haga que la columna de Oracle NO sea NULL. Si alguno es verdadero, haz la columna Oracle NULL. Si ninguno es verdadero, levante la excepción DISEÑO NO VÁLIDO (o tal vez la ignore, si es aceptable para esta aplicación).

Cuando envíe datos de MSSQL a Oracle, simplemente no haga nada especial, todos los datos se transferirán a la derecha. Al recuperar datos en MSSQL, cualquier información no nula debe enviarse como está. Para cadenas nulas, debe decidir si debe insertarse como nulo o como cadena vacía. Para hacer esto, debe verificar nuevamente el diseño de la tabla (o recordar el resultado anterior) y ver si tiene una restricción NOT NULL. Si tiene - use cadena vacía, si no lo ha hecho - use NULL. Simple e inteligente.

A veces, si trabajas con aplicaciones desconocidas e impredecibles, no puedes verificar la existencia de una restricción {cadena vacía} debido a varias formas de la misma. Si es así, puede usar lógica simplificada (hacer que las columnas de Oracle sean siempre anulables) o verificar si puede insertar cadena vacía en la tabla MSSQL sin error.


Es desagradable y podría tener efectos secundarios inesperados ... pero podrías simplemente insertar "chr (0)" en lugar de "".

drop table x drop table x succeeded. create table x ( id number, my_varchar varchar2(10)) create table succeeded. insert into x values (1, chr(0)) 1 rows inserted insert into x values (2, null) 1 rows inserted select id,length(my_varchar) from x ID LENGTH(MY_VARCHAR) ---------------------- ---------------------- 1 1 2 2 rows selected select * from x where my_varchar is not null ID MY_VARCHAR ---------------------- ---------- 1


He escrito una explicación sobre cómo Oracle maneja valores nulos en mi blog hace un tiempo. Compruébelo aquí: http://www.psinke.nl/blog/hello-world/ y avíseme si tiene más preguntas. Si tiene datos de una fuente con valores vacíos y debe convertir a una base de datos Oracle donde las columnas NO SON NULAS, hay dos cosas que puede hacer:

  • eliminar la restricción no nula de la columna de Oracle
  • Verifique cada columna individual si es aceptable colocar una '''' o 0 o una fecha ficticia en la columna para poder guardar sus datos.

Me gustaría ir con una columna adicional en el lado del oráculo. Haga que su columna permita nulos y tenga una segunda columna que identifique si el lado del Servidor SQL debe obtener un valor nulo o una cadena vacía para la fila.


Mi solución típica sería agregar una restricción en SQL Server obligando a todos los valores de cadena en las columnas afectadas a tener una longitud mayor que 0:

CREATE TABLE Example (StringColumn VARCHAR(10) NOT NULL) ALTER TABLE Example ADD CONSTRAINT CK_Example_StringColumn CHECK (LEN(StringColumn) > 0)

Sin embargo, como ha indicado, no tiene control sobre la base de datos SQL. Como tal, realmente tienes cuatro opciones (como yo lo veo):

  1. Trate los valores de cadenas vacías como no válidos, omita esos registros, avise a un operador y registre los registros de alguna manera que facilite la corrección / reingreso manual.
  2. Convierte valores de cadena vacía en espacios.
  3. Convierta valores de cadenas vacías a un código (es decir, "LEGACY" o "VACÍO").
  4. Las transferencias de reversión que encuentran valores de cadena vacíos en estas columnas, luego presionan al propietario de la base de datos de SQL Server para que corrija sus datos.

El número cuatro sería mi preferencia, pero no siempre es posible. La acción que realice realmente dependerá de lo que necesiten los usuarios de Oracle. En última instancia, si no se puede hacer nada con la base de datos SQL, les explico el problema a los propietarios del sistema de negocio de Oracle, les explico las opciones y las consecuencias y les hago tomar una decisión :)

NOTA: Creo que en este caso SQL Server realmente muestra el comportamiento "correcto".


NOT NULL es una restricción de base de datos utilizada para dejar de incluir datos no válidos en su base de datos. Esto no sirve para nada en su base de datos Oracle, por lo que no lo tendría.

Creo que debería continuar permitiendo NULLS en cualquier columna de Oracle que refleje una columna SqlServer que se sabe que contiene cadenas vacías.

Si hay una diferencia lógica en la base de datos SqlServer entre NULL y cadena vacía, entonces necesitaría algo adicional para modelar esta diferencia en Oracle.


No veo una solución fácil para esto.

Tal vez pueda almacenar sus valores como uno o más espacios en blanco -> '' '' , que no son NULLS en Oracle, o realizar un seguimiento de este caso especial a través de campos / tablas adicionales, y una capa de adaptador.


Para aquellos que piensan que un Nulo y una cadena vacía deben considerarse iguales. Un nulo tiene un significado diferente de una cadena vacía. Captura la diferencia entre ''indefinido'' y ''conocido como vacío''. Como ejemplo, un registro puede haber sido creado automáticamente, pero nunca validado por la entrada del usuario, y así recibir un ''nulo'' en la expectativa de que cuando un usuario lo valida, se configurará como vacío. Prácticamente es posible que no deseemos desencadenar la lógica en un nulo, pero es posible que deseemos en una cadena vacía. Esto es análogo al caso de una casilla de 3 estados de Sí / No / Indefinido.

Tanto SQL como Oracle no lo tienen del todo correcto. Un espacio en blanco no debe satisfacer una restricción ''no nula'', y existe la necesidad de que una cadena vacía se trate de manera diferente a como se trata un valor nulo.


Si está migrando datos, puede que tenga que sustituir un espacio por una cadena vacía. No es muy elegante, pero viable. Esta es una desagradable "característica" de Oracle.