Подтвердить что ты не робот

Oracle считает, что пустые строки являются NULL, а SQL Server - нет - как это лучше всего обрабатывается?

Мне нужно написать компонент, который воссоздает таблицы SQL Server (структура и данные) в базе данных Oracle. Этот компонент также должен принять новые данные, введенные в базу данных Oracle, и скопировать их обратно в SQL Server.

Перевод типов данных из SQL Server в Oracle не является проблемой. Однако критическая разница между Oracle и SQL Server вызывает серьезную головную боль. SQL Server считает пустую строку ("") отличной от значения NULL, поэтому столбец char может быть определен как NOT NULL и все же содержать пустые строки в данных.

Oracle считает, что пустая строка будет такой же, как значение NULL, поэтому, если столбец char определяется как NOT NULL, вы не можете вставить пустую строку. Это приводит к тому, что мой компонент разбивается всякий раз, когда столбец NOT NULL char содержит пустую строку в исходных данных SQL Server.

До сих пор моим решением было не использовать NOT NULL в любом из моих зеркальных определений таблиц Oracle, но мне нужно более надежное решение. Это должно быть решением для кода, поэтому ответ не может "использовать такой-то SQL2Oracle продукт".

Как бы вы решили эту проблему?

Изменить: вот единственное решение, которое я придумал до сих пор, и это может помочь проиллюстрировать проблему. Поскольку Oracle не разрешает "в столбце NOT NULL, мой компонент может перехватить любое такое значение, поступающее из SQL Server, и заменить его на" @" (например, например).

Когда я добавляю новую запись в свою таблицу Oracle, мой код должен писать "@", если я действительно хочу вставить "", и когда мой код копирует новую строку обратно на SQL Server, он должен перехватить "@" и вместо этого напишите "".

Я надеюсь, что там будет более элегантный способ.

Изменить 2: Возможно ли, что существует более простое решение, например, некоторые настройки в Oracle, которые позволяют обрабатывать пустые строки так же, как и все другие основные базы данных? И этот параметр также будет доступен в Oracle Lite?

4b9b3361

Ответ 1

Я не вижу легкого решения для этого.

Возможно, вы можете сохранить свои значения как одну или несколько пробелов -> ' ', которые не являются NULLS в Oracle, или отслеживать этот специальный случай через дополнительные поля/таблицы и слой адаптера.

Ответ 2

Моим типичным решением было бы добавить ограничение в SQL Server, заставляющее все строковые значения в затронутых столбцах иметь длину больше 0:

CREATE TABLE Example (StringColumn VARCHAR(10) NOT NULL)

ALTER TABLE Example
ADD CONSTRAINT CK_Example_StringColumn CHECK (LEN(StringColumn) > 0)

Однако, как вы уже заявили, вы не контролируете базу данных SQL. Таким образом, у вас действительно есть четыре варианта (как я вижу):

  • Относитесь к пустым строковым значениям как к недопустимым, пропустите эти записи, предупредите оператора и зарегистрируйте записи каким-либо образом, что упростит правильную или повторную ввод вручную.
  • Преобразование значений пустой строки в пробелы.
  • Преобразование значений пустой строки в код (например, "LEGACY" или "EMPTY" ).
  • Отказоустойчивые передачи, которые сталкиваются с пустыми строковыми значениями в этих столбцах, затем оказывают давление на владельца базы данных SQL Server, чтобы исправить их данные.

Номер четыре будет моим предпочтением, но это не всегда возможно. Действие, которое вы предпринимаете, будет зависеть от того, что нужно пользователям оракула. В конечном счете, если ничего не может быть сделано о базе данных SQL, я бы объяснил проблему владельцам бизнес-систем oracle, объяснил варианты и последствия и заставил их принять решение:)

ПРИМЕЧАНИЕ: Я считаю, что в этом случае SQL Server действительно демонстрирует "правильное" поведение.

Ответ 3

Вам нужно разрешить пустые строки в системе SQL Server? Если вы можете добавить ограничение на систему SQL Server, которая запрещает пустые строки, это, вероятно, самое простое решение.

Ответ 4

Его противный и может иметь неожиданные побочные эффекты.. но вы можете просто вставить "chr (0)", а не ".".

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                      

Ответ 5

NOT NULL - это ограничение базы данных, используемое для остановки ввода недопустимых данных в вашу базу данных. Это не служит никакой цели в вашей базе данных Oracle, и поэтому я бы этого не хотел.

Я думаю, вы должны просто позволить NULLS в любом столбце Oracle отражать столбец SqlServer, который, как известно, содержит пустые строки.

Если существует логическая разница в базе данных SqlServer между NULL и пустой строкой, то вам потребуется что-то дополнительное, чтобы моделировать эту разницу в Oracle.

Ответ 6

Для тех, кто считает, что нуль и пустая строка должны рассматриваться одинаково. Значение null имеет другое значение из пустой строки. Он фиксирует разницу между "undefined" и "известен как пустой". В качестве примера запись могла быть автоматически создана, но никогда не проверена пользовательским вводом и, таким образом, получает "нуль" в ожидании того, что, когда пользователь проверит ее, он будет установлен как пустой. Практически мы не можем запускать логику с нулевым значением, но, возможно, захотим на пустой строке. Это аналогично случаю для 3-го состояния флажка Yes/No/ Undefined.

И SQL, и Oracle не получили его полностью правильно. Бланк не должен удовлетворять ограничению 'не null', и необходимо, чтобы пустая строка обрабатывалась иначе, чем обрабатывается нуль.

Ответ 7

Я бы пошел с дополнительной колонкой на стороне оракула. Пусть в столбце разрешены нули и есть второй столбец, который определяет, должна ли сторона SQL-Server получать нулевое значение или пустую строку для строки.

Ответ 8

Если вы переносите данные, вам может потребоваться заменить пробел для пустой строки. Не очень элегантный, но работоспособный. Это неприятная "особенность" Oracle.

Ответ 9

Я написал объяснение того, как Oracle обрабатывает нулевые значения в моем блоге некоторое время назад. Проверьте это здесь: http://www.psinke.nl/blog/hello-world/ и дайте мне знать, если у вас есть еще вопросы. Если у вас есть данные из источника с пустыми значениями, и вы должны преобразовать их в базу данных Oracle, где столбцы NOT NULL, есть две вещи, которые вы можете сделать:

  • удалить ненулевое ограничение из столбца Oracle
  • Проверяйте для каждого отдельного столбца, если это приемлемо для размещения "или 0" или "фиктивной даты" в столбце, чтобы иметь возможность сохранять ваши данные.

Ответ 10

Ну, главное, что я бы рассмотрел, - это отсутствие задач, когда какое-либо поле может быть нулевым, одно и то же поле может быть пустой строкой, а бизнес-логика требует различать эти значения. Поэтому я бы сделал эту логику:

  • проверить MSSQL, если столбец имеет ограничение NOT NULL
  • проверьте MSSQL, если столбец имеет CHECK (столбец < > '') или подобное ограничение

Если оба значения true, сделайте столбец Oracle NOT NULL. Если кто-то прав, сделайте столбец Oracle NULL. Если ни один из них не является истинным, поднимите исключение INVALID DESIGN (или, возможно, проигнорируйте его, если оно приемлемо для этого приложения).

При отправке данных из MSSQL в Oracle просто ничего не делать, все данные будут переданы правильно. При получении данных в MSSQL любые непустые данные должны быть отправлены как есть. Для нулевых строк вы должны решить, следует ли вставить его как null или пустую строку. Для этого вам нужно снова проверить дизайн таблицы (или запомнить предыдущий результат) и посмотреть, не имеет ли это ограничение NULL. Если есть - используйте пустую строку, если не имеет - используйте NULL. Простой и умный.

Иногда, если вы работаете с неизвестным и непредсказуемым приложением, вы не можете проверить наличие {непустой строки} ограничения из-за его различных форм. Если это так, вы можете использовать упрощенную логику (сделать столбцы Oracle всегда нулевыми) или проверить, можно ли вставить пустую строку в таблицу MSSQL без ошибок.

Ответ 11

Хотя, по большей части, я согласен с большинством других ответов (не собираюсь вступать в спор о каких-либо несогласиях - не место для этого:))

Я замечаю, что OP упомянул следующее:

"Oracle считает, что пустая строка будет такой же, как значение NULL, поэтому, если столбец char определяется как NOT NULL, вы не можете вставить пустую строку."

В частности, вызывается CHAR, а не VARCHAR2. Следовательно, говорить о "пустой строке" длины 0 (т.е. '') Является спорным. Если он объявит char как, например, CHAR (5), просто добавьте пробел в пустую строку, входящую в систему, и Oracle все равно будет ее заполнять. В итоге вы получите 5 пробелов.

Теперь, если OP означал VARCHAR2, ну да, это целый другой зверь, и да, разница между пустой строкой и NULL становится актуальной.

  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>