powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Перевод из MS SQL Server в ORACLE
120 сообщений из 120, показаны все 5 страниц
Перевод из MS SQL Server в ORACLE
    #39209269
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день господа!

Стоит задача у меня: перевести готовую базу из MS SQL Server в ORACLE. Я очень и очень плохо знаю ORACLE, не все получается.
Есть несколько вопросов.

Как я понимаю в Oracle нет функции ISNUMERIC. Написал собственную функцию.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE OR REPLACE Function dbo.f_IsNumeric (Expression Varchar)
    Return Number Is X Number(1, 0);
Begin
    If Length(
        Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Expression,
            '0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')) = 0 Then
        X := 1;
    Else
        X := 0;
    End If;

    Return (X);
End;


Может есть попроще? Функция проверяет только целые числа, пока мне и этого достаточно.

В MS SQL Server можно создать скалярную функцию (не знаю как называется в Oracle), которую можно использовать в Constraint, чтобы ставить ограничение при вводе данных. Можно ли и в Oracle использовать собственную функцию?
Попробовал вот так по аналогию с MS SQL Server. Не получается.
Код: plsql
1.
2.
ALTER TABLE Table1 ADD  CONSTRAINT CK_Table1 CHECK 
(dbo.f_IsNumeric (Field1)=1)



Спасибо заранее за подсказку / ссылку и т.п.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209271
Vint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
может стоит научиться пользоваться поиском? тогда и писать надо будет меньше...
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209273
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vint,

Искал. Не нашёл. Поэтому написал.
Если знаете как в constraint использовать собственную функцию подскажите please.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209275
Anatoly B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,
авторИскал. Не нашёл
https://community.oracle.com/thread/373057?start=0
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209280
Vint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209285
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly B,

Спасибо за ссылку, но там нет то, что я ищу.
Как в constraint использовать собственную функцию?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209287
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenМожно ли и в Oracle использовать собственную функцию?
В Oracle можно объявить поле типа NUMBER и оно автоматически будет ограничено только числами.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209292
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vintstudieren,
звиздиш. ленивый нуб.
Ну и где же написано как можно применить собственную функцию в constraint?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209296
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovstudierenМожно ли и в Oracle использовать собственную функцию?
В Oracle можно объявить поле типа NUMBER и оно автоматически будет ограничено только числами.

К сожалению не могу. Там 9-значные цифры, первая цифра "0". Если объявить как число, то первый символ пропадёт.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209306
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В check-констрейнте нельзя использовать самописные функции
Но тебе достаточно TRANSLATE
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209310
MakeSure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почему бы просто не создать поле с типом NUMBER?

translate в помощь по поводу цифр в строке.
У Check constraint есть ограничения, например, нельзя использовать самописные функции. А вот засутить translate в сам констрэинт можно.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209313
MakeSure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл обновиться =\
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209319
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenК сожалению не могу. Там 9-значные цифры, первая цифра "0". Если объявить
как число, то первый символ пропадёт.
Это всего лишь проблема форматирования при выводе.

Но даже если держать это значение как строку, пользовательская функция не нужна пока есть
regexp_like. Достаточно научиться писать регэкспы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209324
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав ЛюбомудровВ check-констрейнте нельзя использовать самописные функции
Но тебе достаточно TRANSLATE

Dimitry SibiryakovЭто всего лишь проблема форматирования при выводе.

Но даже если держать это значение как строку, пользовательская функция не нужна пока есть
regexp_like. Достаточно научиться писать регэкспы.
Спасибо за наводку, не знал что нельзя. Сейчас попробую TRANSLATE или regexp_like.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209338
р/лтрим
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studieren,

(само)введение в заблкждение. лидирующий ноль означает, что данные у тебя не число, а строка, состоящая из цифр. и msный isnumeric не обеспечивает проверки, что строка из только цифр.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209384
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

Посмотрите эти продукты
- Database Migration Guide (12с)
- 2. SQL Developer: Migrating Third-Party Databases
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209400
MakeSure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пост "р/лтрим" сфокусировал правильно вопрос.

Должно быть быстрее так (да и учитывает не только целые числа):
Код: plsql
1.
nvl(1,to_number(rec.a)) = 1 
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209406
MakeSure
Код: plsql
1.
nvl(1,to_number(rec.a)) = 1 


К сожалению, это нестабильный код, поскольку зависит от окружения сессии.
Конкретно - от NLS_NUMERIC_CHARACTERS
Поправить - просто, примеров на форуме - мульон, особенно от нашего официального тирана Elic
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209414
MakeSure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Преобразователь Неявный,
само собой по нлс параметры надо позаботиться.
Я, в целом, о том, что транслэйт тут будет значительно медленней, чем to_number. К тому же to_number вызовет ошибку более читабельную.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209445
MakeSure
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UPD

Еще учесть надо to_number('3E10')
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209450
MakeSureUPD

Еще учесть надо to_number('3E10')
Учесть надо второй и третий параметр to_number, блин.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209533
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
SQL> create table tbl(
  2                   numeric_string varchar2(4000)
  3                  )
  4  /

Table created.

SQL> create index is_number
  2    on tbl(
  3           to_number(numeric_string)
  4          )
  5  /

Index created.

SQL> insert into tbl values('-1.5');

1 row created.

SQL> insert into tbl values('XYZ');
insert into tbl values('XYZ')
*
ERROR at line 1:
ORA-01722: invalid number


SQL> insert into tbl values(lpad('1',200,'1'));
insert into tbl values(lpad('1',200,'1'))
*
ERROR at line 1:
ORA-01426: numeric overflow


SQL>  



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
SQL> create table tbl(
  2                   numeric_string varchar2(4000)
  3                  )
  4  /

Table created.

SQL> alter table tbl
  2    add constraint tbl_chk1
  3      check(
  4            to_number(numeric_string) - to_number(numeric_string) = 0
  5           )
  6  /

Table altered.

SQL> insert into tbl values('-1.5');

1 row created.

SQL> insert into tbl values('XYZ');
insert into tbl values('XYZ')
           *
ERROR at line 1:
ORA-01722: invalid number


SQL> insert into tbl values(lpad('1',200,'1'));
insert into tbl values(lpad('1',200,'1'))
           *
ERROR at line 1:
ORA-01426: numeric overflow


SQL> 



SY.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39209544
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
Код: plsql
1.
2.
3.
4.
5.
6.
SQL> insert into tbl values('XYZ');
insert into tbl values('XYZ')

*
ERROR at line 1:
ORA-01722: invalid number



SY.плохо, что ошибка неявная и х.з. где возникает
через год юзверь позвонит в полтретьего ночи - че за фигня? потом хрен вспомнишь, что это твой же констрейнт по его же ТЗ
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39210808
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возник ещё 1 вопрос. Хотел установить ограничение на дату документа (запретить на ввод будущей даты). Запускаю скрипт, а ORCLE ругается:
Код: plsql
1.
2.
3.
alter table dbo.Table1
  add constraint CK_Table1_DocDate
  check (DocDate <= trunc(sysdate));


Ругается так:
Oracle Error: ORA-02436
Date or system variable wrongly specified in CHECK constraint


А как надо было написать? Разве нельзя использовать SYSDATE?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39210814
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenРазве нельзя использовать SYSDATE?RTFM Restrictions on Check Constraints (FAQ)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39210826
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,

Спасибо за ссылку. Правильно ли я понял, что в CONSTRAINT нельзя устанавливать запрет на будущую дату, т.к. в этом случае мне пришлось бы использовать "functions that are not deterministic"?
Только в триггере могу ставить такое ограничение?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39210870
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenПравильно ли я понялПолагаешь, документация тебя обманывает?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39213523
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую форумчан!

Как получить весь список внешних ключей?
В MS SQL Server запрос примерно выглядел бы так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT
	SC.name AS SchemaName,
	MT.name AS MainTableName,
	ST.name AS SubordinatedTableName,
	FK.name AS ForeignKey,
	FK.is_disabled AS IsDisabled
FROM sys.foreign_keys FK INNER JOIN sys.objects MT ON FK.referenced_object_id = MT.object_id
	INNER JOIN sys.objects ST ON FK.parent_object_id = ST.object_id
	INNER JOIN sys.schemas SC ON ST.schema_id = SC.schema_id
ORDER BY FK.is_disabled DESC, SC.name, MT.name;


А как в ORACLE не знаю. :(

Спасибо заранее за помощь.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39213555
Фотография Viewer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39213570
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Viewer,

Thank you very much.
Ушёл изучать скрипты.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39213576
tbl2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenКак получить весь список внешних ключей?
sys.foreign_keys -> dba_constraints (type = 'R')
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39213578
Фотография Viewer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39219746
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В MS Sql Server в триггерах можно ссылаться на логические таблицы "Inserted" и "Deleted". В таблице "Inserted" все введённые новые записи, а в "Deleted" соответственно все удаленные записи.

Как я понял в Oracle я должен добавить перед полем ":new." или ":old.", чтобы получить новое и старое значение. Но это немножко не то. Мне нужно именно в виде таблицы, что-то вроде "Inserted" и "Deleted".
Что для этого надо делать?

P.S.
Хотел создать временную таблицу "на лету" как в MS Sql Server и добавить туда все ":new." и ":old.", ну так в ORACLE нет временных таблиц как в MS Sql Server. Как выйти из ситуации? :(
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39219760
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenКак выйти из ситуации?Менять мировоззрение, читая документацию.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220135
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то я не понимаю. Написал триггер на вставку и на изменение. Если в таблице меняю что-то, то ORACLE ругается " ... is mutating, trigger/function may not see it ". Прочёл в вышеуказанной ссылке (в предыдущем посте), что нужно написать какой-то COMPOUND TRIGGER при чём для VIEW. Т.е. чтобы триггер у меня начал работать так как мне надо, сначала создаю VIEW и пишу триггер на VIEW. А почему сразу не на таблицу? Бред какой-то. Зачем мне лишнее представление?
В MS SQL Server проще простого. :(
Может я не правильно понимаю?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220141
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНаписал триггер на вставку и на изменение. Если в таблице меняю что-то

А что, просто присвоить нужные новые значения :new не судьба?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220282
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

После многочисленных экспериментов путём проб и ошибок выяснил следующее:
если триггер на изменение (не важно BEFORE или AFTER), то внутри тела триггера нельзя оказывается ссылаться на таблицу триггера (т.е. на ту таблицу, для которой был написан собственно сам триггер).
Пример.
Допустим у меня есть таблица "Контракт" и есть "Платежи". Хочу скажем проверить общую сумму всех платежей, которая согласно бизнес правилам не должна превышать сумму контракта. Пишу триггер для платежей.
Допустим кто-то ввел 2 платежа: 1000$ и 500$, общая сумма не превышает сумму контракта (1500$). Но кто-то решил подкорректировать сумму: вместо 1000 скажем 1100. Вот тут триггер должен запретить изменение, т.к. общая сумма в таком случае получится 1600$. И как же тогда мне нужно узнать общую сумму платежей?

P.S.
В MS SQL Server нет таких ограничений, можно изменяемые записи сверять со всей таблицей.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220294
studieren нет таких ограниченийотвлекись от триггера и подумай, что будет, если два пользователя одновременно вставляют в пределах лимита, но более половины.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220301
tru55
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220302
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
афтер статемент,

В любом случае общая сумма не должна превышать. Тот, кто первым успел сохранить "правильные" данные, то его данные должны быть в базе данных. А тот, кто опоздал и его данные уже "кривые", вот тут программа пусть ругает как следует.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220308
eev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
авторДопустим у меня есть таблица "Контракт" и есть "Платежи". Хочу скажем проверить общую сумму всех платежей, которая согласно бизнес правилам не должна превышать сумму контракта. Пишу триггер для платежей.
Допустим кто-то ввел 2 платежа: 1000$ и 500$, общая сумма не превышает сумму контракта (1500$). Но кто-то решил подкорректировать сумму: вместо 1000 скажем 1100
...
В MS SQL Server нет таких ограничений вопрос, мона?
т.е. если в одном операторе insert вставляешь 2 записи. (нет ещё коммита) и другой меняет (пытается) одну из вставляемых записей. то 1-ая вставка insert увидит изменения от 2-ой? так?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220310
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenА тот, кто опоздал и его данные уже "кривые", вот тут программа пусть
ругает как следует.
Обломись. Триггерами (в особенности такими) этого не сделать. Открой для себя мир
транзакций с уровнем выше чем dirty read.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39220313
studierenкто первым успел сохранитья тебе предлагал подумать, а не продолжать демонстрировать непонимание изоляции транзакций.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222065
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tru55про мутацию
http://www.sql.ru/faq/faq_topic.aspx?fid=513
Спасибо за ссылку. Прочёл несколько раз, но так и не смог осилить как адаптировать в моём случае.
Не могли бы подсказать?
Допустим есть таблица "контракт".
Код: plsql
1.
2.
3.
4.
5.
6.
7.
Create table Contract
(ContractID Int not null,
ContractNumber varchar2(20) not null,
ContractDate date not null,
Currency char(3) not null,
Amount Number(14, 2) not null,
constraint PK_Contract PRIMARY KEY (ContractID));


Есть также "платежи"
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
create table Payment
(ContractID Int not null,
PaymentDate date not null,
Currency char(3) not null,
Amount number(14, 2) not null,
constraint PK_Payment PRIMARY KEY (ContractID, PaymentDate));
/
ALTER TABLE Payment ADD CONSTRAINT FK_Payment_Contract FOREIGN KEY(ContractID)
REFERENCES Contract (ContractID);


Добавляем записи.
Код: plsql
1.
2.
3.
4.
5.
6.
Insert into Contract
Select 1, '1', to_date('20160401', 'YYYYMMDD'), 'USD', 15000 From dual;
/
Insert into Payment
Select 1, to_date('20160405', 'YYYYMMDD'), 'USD', 1000 From Dual
Union All Select 1, to_date('20160406', 'YYYYMMDD'), 'USD', 500 From Dual


Теперь мне нужно запретить пользователю внести любые изменения в сумме платежа, если общая сумма превышает сумму контракта. Как это сделать в Oracle не знаю.
Скажу честно, моего уровня знания не хватает в данном вопросе. Я недавно стал изучать ORACLE.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222073
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пересчитывать сумму в родительской записи, а на нее уже повесить проверку
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222079
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

В смысле в таблицу "Contract" добавить вычисляемое поле и триггер добавить туда?
Допустим, я так и сделаю. Когда пользователь попытается исправить в платежах, разве триггер контракта тоже заработает?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222086
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

Или я не правильно понял?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222108
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да правильно
Примерно так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
tst> create table contract(id number primary key, cur_sum number default 0, max_sum number default 15000);

Table created.

tst> create table payment(id number primary key, c_id number references contract, ammount number);

Table created.

tst> create trigger contr_trg before insert or update on contract
  2  for each row
  3  begin if inserting then
  4           :new.cur_sum := 0;
  5        end if;
  6        if :new.cur_sum > :new.max_sum then
  7           raise_application_error(-20001, 'Cur_sum ('||:new.cur_sum||') > max_sum ('||:new.max_sum||')');
  8        end if;
  9  end;
 10  /

Trigger created.

tst> create trigger paym_trg after insert or update or delete on payment
  2  for each row
  3  begin update contract set cur_sum = cur_sum + nvl(:new.ammount, 0) - nvl(:old.ammount, 0);
  4  end;
  5  /

Trigger created.

tst> insert into contract values(1, 0, 100);

1 row created.

tst> insert into payment values(1, 1, 20);

1 row created.

tst> select * from contract;

        ID    CUR_SUM    MAX_SUM
---------- ---------- ----------
         1         20        100

tst> insert into payment values(2, 1, 90);
insert into payment values(2, 1, 90)
            *
ERROR at line 1:
ORA-20001: Cur_sum (110) > max_sum (100)
ORA-06512: at "U1.CONTR_TRG", line 5
ORA-04088: error during execution of trigger 'U1.CONTR_TRG'
ORA-06512: at "U1.PAYM_TRG", line 1
ORA-04088: error during execution of trigger 'U1.PAYM_TRG'


tst> update payment set ammount=10 where id=1;

1 row updated.

tst> insert into payment values(2, 1, 90);

1 row created.

tst> select * from contract;

        ID    CUR_SUM    MAX_SUM
---------- ---------- ----------
         1        100        100

tst> select * from payment;

        ID       C_ID    AMMOUNT
---------- ---------- ----------
         1          1         10
         2          1         90

tst> 

...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222123
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

Спасибо. Я понял Вашу мысль. Любое изменение в платежах нужно с помощью триггера отразить в дополнительном поле в контрактах. Если сумма превышает, то тогда и происходит исключение.
ОК. Если не найду другое решение, то так и сделаю.

Может есть ещё вариант?
К сожалению, не всегда такое решение для меня приемлемо. Есть ещё сложные проверки данных в других таблицах на предмет пересекающихся диапазонов, вот там я в любом случае должен просмотреть все записи в "мутирующей" таблице.


Хорошо, создам дополнительное представление (view) и туда попробую внедрить триггер. Если не ошибаюсь Compound trigger (или как там правильно называется?). Соответственно в клиентском приложении тогда буду иметь дело только с view.
Как тогда решается проблема?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222158
eev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren Если не ошибаюсь Compound trigger (или как там правильно называется?). Соответственно в клиентском приложении тогда буду иметь дело только с view.
Как тогда решается проблема?
19080443 Using Compound DML Triggers to Avoid Mutating-Table Error с примером
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222159
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты путаешь INSTEAD OF триггер (на VIEW) и COMPAUND триггер. Последний -- это просто объединение триггеров на разные события в одном куске кода, что удобней при использовании например локальных PL/SQL коллекций для обхода той же мутации.
Типо: в секции BEFORE STATEMENT заполняешь коллекцию текущим состоянием, а затем в секциях BEFORE/AFTER EACH ROW проверяешь не нарушает ли условие конкретная запись (на основании коллекции, чтоб не лезть в таблицу). При этом ты, естественно, не видишь изменений других сеансов (добавленных строк, например) и если не предусмотрена какая-либо сериализация (та же блокировка родительской записи) -- все твоя проверка может пойти лесом
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222165
checkъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вячеслав Любомудровcreate trigger contr_trg before insert or update on contractиспользовать триггер для проверки допустимости значения очень однопло.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222168
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не спорю, CHECK намного лучше
А еще и индекс на FOREIGN KEY построить

Но это таки пример -- вводить и объяснять новые понятия нет желания
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222181
dba123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВячеслав Любомудров,

Спасибо. Я понял Вашу мысль. Любое изменение в платежах нужно с помощью триггера отразить в дополнительном поле в контрактах. Если сумма превышает, то тогда и происходит исключение.
ОК. Если не найду другое решение, то так и сделаю.
только внимательней со своим кодом, а то апдейт фк может не сработать, как мне показалось
Код: plsql
1.
update payment set c_id = 1 where c_id = 2;
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222192
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав ЛюбомудровТы путаешь INSTEAD OF триггер (на VIEW) и COMPAUND триггер. Последний -- это просто объединение триггеров на разные события в одном куске кода, что удобней при использовании например локальных PL/SQL коллекций для обхода той же мутации.
Типо: в секции BEFORE STATEMENT заполняешь коллекцию текущим состоянием, а затем в секциях BEFORE/AFTER EACH ROW проверяешь не нарушает ли условие конкретная запись (на основании коллекции, чтоб не лезть в таблицу). При этом ты, естественно, не видишь изменений других сеансов (добавленных строк, например) и если не предусмотрена какая-либо сериализация (та же блокировка родительской записи) -- все твоя проверка может пойти лесом
Ну допустим, пользователь по конкретному контракту только 1, в смысле если я ввожу данные по одному контракту, то никто параллельно в этот момент не работает с данным контрактам. Соответственно, исключаем возможность других сеансов по конкретной записи. Или другой пример. Допустим я единственный пользователь базы.
Т.е. пусть даже триггер не видит, что делают другие пользователи, а имеет дело только с конкретным пользователем. Я хочу исправить сумму платежа на большую и тут триггер должен меня остановить сообщив об ошибке. Неужели триггер на изменение никак не может просмотреть всю таблицу только по данному контракту? Неужели в корпорации ORACLE не предусмотрели такой поворот событий? Почему то в MS SQL Server нет таких проблем вообще.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222314
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenПочему то в MS SQL Server нет таких проблем вообще.
MS SQL - тупой блокировочник. Фактически, он работает в однопользовательском режиме.
Поэтому у него нет проблем с конкурентным доступом к данным.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222324
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovstudierenПочему то в MS SQL Server нет таких проблем вообще.
MS SQL - тупой блокировочник. Фактически, он работает в однопользовательском режиме.
Поэтому у него нет проблем с конкурентным доступом к данным.

Я с Вами не согласен. В MS SQL Server с одной таблицей могут работать сразу несколько пользователей и при этом триггер спокойно видит все сохранённые данные. Да, там тоже может быть блокировка, но как правило, так происходит если 2 пользователя правят одну и ту же запись. Вот тогда тот, кто успел первым сохранить, то его данные и будут в базе. А у второго - ошибка блокировки. Но на практике одну и ту же запись 2 пользователя почти никогда не правят.
Поэтому кто тупой, MS SQL Server или ORACLE в данном вопросе очень и очень спорно!
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222339
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dba123studierenВячеслав Любомудров,

Спасибо. Я понял Вашу мысль. Любое изменение в платежах нужно с помощью триггера отразить в дополнительном поле в контрактах. Если сумма превышает, то тогда и происходит исключение.
ОК. Если не найду другое решение, то так и сделаю.
только внимательней со своим кодом, а то апдейт фк может не сработать, как мне показалось
Код: plsql
1.
update payment set c_id = 1 where c_id = 2;

Все, заклевали
Нафиг я сюда вообще влез

studierenНу допустим, пользователь по конкретному контракту только 1, в смысле если я ввожу данные по одному контракту, то никто параллельно в этот момент не работает с данным контрактам. Соответственно, исключаем возможность других сеансов по конкретной записи. Или другой пример. Допустим я единственный пользователь базы.Такие допущения надо чем-то обеспечить
studierenПочему то в MS SQL Server нет таких проблем вообще.Просто они разные
Когда ты изменяешь несколько строк одним оператором и пытаешься (в триггере для каждой обновленной строки) например, подсчитать сумму в этих строках, то возникает вопрос, на какой момент времени брать значения? Точнее даже какой именно из возможных -- ты не можешь управлять порядком обновления/удаления/вставки строк (при многострочной обработке) и при другом порядке (который выбирает Oracle) результат будет другой.

Возьмем твой пример -- ограничить сумму в 1500
Пусть у нас есть строки со значениями: 1000, 500, -1000
Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3
То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п.
Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо

Вот от такой неоднозначности тебя Oracle и страхует
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222345
dba123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

Дык он студент вроде, кто знает, что он там напишет :)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222351
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВ MS SQL Server с одной таблицей могут работать сразу несколько
пользователей и при этом триггер спокойно видит все сохранённые данные.
Уверен? Проверь на своей схеме следующий сценарий:
1) Сессия 1 стартует транзакцию
2) Сессия 2 стартует транзакцию.
3) Сессия 1 добавляет к документу строку, полностью выбирающую лимит.
4) Сессия 2 добавляет к тому же документу вторую строку, полностью выбирающую лимит.
5) Сессия 1 коммитится.
6) Сессия 2 коммитится.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222430
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пардон, если баян - тему читал по оч. большой диагонали

studieren,

в sql оракловом есть несколько функций каждой из которых достаточно, для создания подходящего вашей теме
проверочного констрейнта

например, ltrim(ляля,'0123456789') is null
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222583
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
orawishпардон, если баян - тему читал по оч. большой диагонали

studieren,

в sql оракловом есть несколько функций каждой из которых достаточно, для создания подходящего вашей теме
проверочного констрейнта

например, ltrim(ляля,'0123456789') is null
Ту проблема я уже решил с помощью regexp_like (спасибо товарищам за подсказку).
Теперь у меня совсем другая проблема.
Когда пользователь правит какую-либо таблицу (мутирующая таблица), то мне необходимо ставить такое ограничение, которое проверяет все записи мутирующей таблицы и если что не так, то запрещает внесение изменений. При этом даже если предположить, что где-то другой пользователь пытается внести изменение в данную таблицу, то эти изменения игнорировать если данные фактически ещё НЕ СОХРАНЕНЫ!
Как это сделать? Не пойму.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222588
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров...
Возьмем твой пример -- ограничить сумму в 1500
Пусть у нас есть строки со значениями: 1000, 500, -1000
Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3
То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п.
Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо

Вот от такой неоднозначности тебя Oracle и страхует

В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так.

А вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222608
eev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВячеслав Любомудров...
Возьмем твой пример -- ограничить сумму в 1500
Пусть у нас есть строки со значениями: 1000, 500, -1000
Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3
То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п.
Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо

Вот от такой неоднозначности тебя Oracle и страхует

В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так.

А вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ. ты откуда ж такого фееричного бреда понабрал-то...
а про мутирующие таблицы тебе уже 2 страницы разжевывают. пишет и пишет, говорят ему доку открой, "ну-не-пойму-я" заклинило :).
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222614
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВячеслав Любомудров...
Возьмем твой пример -- ограничить сумму в 1500
Пусть у нас есть строки со значениями: 1000, 500, -1000
Если мы сделаем UPDATE TABLE SET AMOUNT = AMOUNT*3
То, если строки будут обновляться в прямом порядке, то после обновления первой строки мы получим (1000*3)+(500)+(-1000) = 2500, что уже больше 1500, и значит все плохо, так делать нельзя и т.п.
Если же мы обновляем с конца, то после обновления всех строк получаем (1000*3)+(500*3)+(-1000*3) = 1500, что оказывается неплохо, можно даже сказать, хорошо

Вот от такой неоднозначности тебя Oracle и страхует

В MS SQL Server когда массово что-то меняете и при этом хотя бы одна запись даёт "сбой", то сервер запрещает все изменения и происходит откат. Жаль, что в ORACLE не так. Ты нихрена не понял
Вопрос в непредсказуемости результата
studierenА вообще обычно юзеры штучно правят записи, массово что-то менять может только админ базы или специалист ИТ.Какое-то извращенное понятие, можно подумать БД разбирается -- обычный это юзер или "специалист ИТ"
На одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибки
Именно потому, что результат детерминирован
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222625
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВ MS SQL Server когда массово что-то меняете и при этом хотя бы одна
запись даёт "сбой", то сервер запрещает все изменения и происходит откат.
Вот только твой триггер не даст "сбой". Сценарий я описал выше.

Триггерами можно обеспечить целостность группы записей только на уровне изоляции DIRTY
READ. Которого в Oracle нет.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222640
ну-ну...
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry SibiryakovТриггерами можно обеспечить целостность группы записей только на уровне изоляции DIRTY
READ. Которого в Oracle нет.
целостность и dirty read. целостность можно обеспечить при любом уровне изоляции, кроме dirty read.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222644
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

ОК.
Вот ещё одна проблема. Я должен хранить серийные номера "от" и "до" в разных полях/столбцах. При этом серийные номера не в коем случае не должны пересекаться.
Скажем, в таблице есть такие данные:
От До1 1020 30
Если я попытаюсь ввести диапазон 7 и 11 программа должна ругаться, так как внутри диапазона 1 и 10 уже есть хотя бы как минимум 1 элемент из 7 и 10. Неужели в ORACLE я не смогу создать такой запрет?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222651
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНеужели в ORACLE я не смогу создать такой запрет?
Сможешь. Но работать правильно он будет исключительно в однопользовательском режиме. Как и
в любой другой СУБД кроме тех, которые выше DIRTY READ ничего не умеют.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222662
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenТ.е. пусть даже триггер не видит, что делают другие пользователи, а имеет дело только с конкретным пользователем.
В этом то вся и проблема. В этом самом конкретном пользователе. Другие фиг с ними - он не закоммитились - их нет.
Oracle версионник. А это значит, что он не возвращает данные, которые есть в базе. Он возвращает данные на какой-то момент времени (иногда оп выбору иногда на усмотрение сервера). Основная операция еще не завершилась - поэтому ее результата еще нет. И в том числе для триггера. Если так сделать Вы же первый взвоете - какого черта? Ну и в большинстве случаев подобный подход, когда проверяется верность несогласованного набора данных, чаще всего нужно тем, кто хочет совершить ошибку. Поэтому Oraclke СУБД и выплевывает ошибку в этот момент.

Простой пример. Вы всегда хотите, чтобы сумма чего-то разложенного по полкам была равна константе. Тогда Вы не сможете одной операцией увеличить значение на одной полке и уменьшить на другой, если будете проверять сумму по ходу операции. Для этого надо проверять сумму после операции. О чем и сигнализирует ошибка. :)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222677
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНеужели в ORACLE я не смогу создать такой запрет?
Можешь. Но делается это иначе. Делается мат вью, которое возвращает количество пересекающихся интервалов, обновляемое по commit. И constraint который не позволяет количеству пересекающихся интервалов быть больше 0.
Одна проверка на транзакцию. Не на каждое изменение.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222688
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну или iot табличку с уникальными номерами (вставляем для всего диапазона).
Заодно можно получить отлуп (взаимная блокировка), если кто-то еще пытается вместе с вами работать в том же направлении. :)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222689
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав ЛюбомудровНа одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибкиВставках.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39222708
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ElicВячеслав ЛюбомудровНа одиночных обновлениях триггер BEFORE ... FOR EACH ROW тоже отработает без ошибкиВставках.Упс...
Точно
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223554
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав Любомудров,

Прочёл книжку "ORACLE PL/SQL Как писать мощные и гибкие программы на PL/SQL" Кристофер Аллен.
Там нашёл ответ на свою проблему. Вот отрывок:
Когда триггер пытается прочитать таблицу, а затем записать в нее
данные, возбуждается исключение "мутирующей таблицы". Хотя
намерение ограничить действия такого типа вполне объяснимо,
корпорация Oracle зашла в этом дальше, чем необходимо, запретив
операции, при которых таблица просто блокируется, а не изменяется.
Один из способов обойти эту проблему заключается в том, чтобы
создать вторую таблицу с копиями столбцов, которые триггер должен
прочитать из главной таблицы. В этом случае триггер получает
необходимые значения из второй таблицы, а затем выполняет
запланированные действия с первой таблицей. При реализации
данного подхода важно обеспечить синхронизацию таблиц. Для этого
все операции INSERT, UPDATE и DELETE над главной таблицей
должны отражаться триггером на второй таблице.
Т.е. создаю таблицу точь в точь с "оригиналом", туда добавляю все изменения (вставка, изменение, удаление). Все необходимые мне проверки провожу во второй таблице.
Ну если это единственный способ, что поделать! Буду так. Но я в шоке от корпорации ORACLE.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223562
tru55
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНу если это единственный способ, что поделать!
В FAQ написано, как использовать коллекции из пакета, а отнюдь не отдельную таблицу.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223570
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tru55studierenНу если это единственный способ, что поделать!
В FAQ написано, как использовать коллекции из пакета, а отнюдь не отдельную таблицу.
Не смог осилить. Можете простенький пример показать? Да хоть в примере "контракты" и "платежи".

Мне показалось, что там в FAQ не мой случай.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223599
eev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenНе смог осилить. Можете простенький пример показать? Да хоть в примере "контракты" и "платежи".

Мне показалось, что там в FAQ не мой случай.

простенький пример из документации
Example 9-10 Compound Trigger Avoids Mutating-Table Error\
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
CREATE OR REPLACE TRIGGER Check_Employee_Salary_Raise
  FOR UPDATE OF Salary ON Employees
COMPOUND TRIGGER
  Ten_Percent                 CONSTANT NUMBER := 0.1;
  TYPE Salaries_t             IS TABLE OF Employees.Salary%TYPE;
  Avg_Salaries                Salaries_t;
  TYPE Department_IDs_t       IS TABLE OF Employees.Department_ID%TYPE;
  Department_IDs              Department_IDs_t;

  -- Declare collection type and variable:

  TYPE Department_Salaries_t  IS TABLE OF Employees.Salary%TYPE
                                INDEX BY VARCHAR2(80);
  Department_Avg_Salaries     Department_Salaries_t;

  BEFORE STATEMENT IS
  BEGIN
    SELECT               AVG(e.Salary), NVL(e.Department_ID, -1)
      BULK COLLECT INTO  Avg_Salaries, Department_IDs
      FROM               Employees e
      GROUP BY           e.Department_ID;
    FOR j IN 1..Department_IDs.COUNT() LOOP
      Department_Avg_Salaries(Department_IDs(j)) := Avg_Salaries(j);
    END LOOP;
  END BEFORE STATEMENT;

  AFTER EACH ROW IS
  BEGIN
    IF :NEW.Salary - :Old.Salary >
      Ten_Percent*Department_Avg_Salaries(:NEW.Department_ID)
    THEN
      Raise_Application_Error(-20000, 'Raise too big');
    END IF;
  END AFTER EACH ROW;
END Check_Employee_Salary_Raise;
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223608
studieren,

С подходом чтения изменяемой таблицы в триггере этого не решить без блокировки мастер-ключа. У dbms_lock свои недостатки при интенсивном использовании большого количества значений, да еще коммит на аллокейт. Можно, конечно, эксклюзивить всю таблицу.
Посему, в оракле предпочитают использовать более оракловые подходы ограничения агрегатов промеж строк. Или вообще не ограничивать на стороне БД. Мало ли, какие еще нереляционные сложносвязанные бизнес-требования могут применяться в приложении.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223637
Вячеслав Любомудров
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenВячеслав Любомудров,Не очень понятно, почему ты мне это адресуешь

studierenПрочёл книжку "ORACLE PL/SQL Как писать мощные и гибкие программы на PL/SQL" Кристофер Аллен.Судя по написаному, читать такое не стоит

studierenНу если это единственный способ, что поделать! Буду так. Но я в шоке от корпорации ORACLE.Это самый извращенный способ, мне, честно говоря, и в голову такое прийти не могло (правда, я не разработчик).

По-поводу шока, ты так и не сказал, как нужно вести себя (твое ограничение в 1500 на сумму платежей)
я использую все тот же пример
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
tst> create table payment(id number, contr_id number /* номер контракта */, amount number);

Table created.

tst> insert into payment /* ну вот в таком порядке вводились данные */
  2  select 1 id, 1 contr_id, 1000 amount from dual union all
  3  select 2 id, 1 contr_id, 500 amount from dual union all
  4  select 3 id, 1 contr_id, -1000 amount from dual union all
  5  select rownum + 3 id, trunc(rownum/3)+2, mod(rownum, 3)*500 from dual connect by level <= 10; /* здесь какие-то другие данные */

13 rows created.

tst> create trigger paym_trg
  2  for update on payment
  3  compound trigger
  4      type amount_table is table of number;
  5      a_t amount_table;
  6      cur_sum number;
  7  before statement is
  8  begin /* это пример, поэтому мы работаем только с контрактом 1 */
  9      select amount bulk collect into a_t
 10      from payment where contr_id=1 order by id; 
 11      dbms_output.put_line('Before statement');
 12      for i in 1..a_t.count loop /* чтоб не лезть в таблицу -- сохраняем данные в локальную PL/SQL коллекцию перед началом оператора */
 13          dbms_output.put_line('--- id='||i||', a_t(i)='||a_t(i));
 14      end loop;
 15  end before statement;
 16  before each row is
 17  begin
 18      cur_sum := 0;
 19      a_t(:new.id) := a_t(:new.id) - :old.amount + :new.amount; /* и синхронно обновляем запись в локальной коллекции */
 20      dbms_output.put_line('Update row with id='||:new.id);
 21      for i in 1..a_t.count loop
 22          dbms_output.put_line('--- id='||i||', a_t(i)='||a_t(i));
 23          cur_sum := cur_sum + a_t(i); /* подсчитываем сумму для контракта при обновлении каждой строки */
 24      end loop;
 25      dbms_output.put_line('Current sum='||cur_sum);
 26      if cur_sum > 1500 then  /* вот тут нам по-идее нужно генерить ошибку и прерывать оператор */
 27          dbms_output.put_line('!!! ERROR !!!');
 28      end if;
 29  end before each row;
 30  end;
 31  /

Trigger created.

Обновляем несколько строк
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
tst> set serveroutput on
tst> update payment set amount=amount*3 where contr_id=1;
Before statement
--- id=1, a_t(i)=1000
--- id=2, a_t(i)=500
--- id=3, a_t(i)=-1000
Update row with id=1
--- id=1, a_t(i)=3000
--- id=2, a_t(i)=500
--- id=3, a_t(i)=-1000
Current sum=2500
!!! ERROR !!!
Update row with id=2
--- id=1, a_t(i)=3000
--- id=2, a_t(i)=1500
--- id=3, a_t(i)=-1000
Current sum=3500
!!! ERROR !!!
Update row with id=3
--- id=1, a_t(i)=3000
--- id=2, a_t(i)=1500
--- id=3, a_t(i)=-3000
Current sum=1500

3 rows updated.

Просто добавили индекс
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
tst> rollback;

Rollback complete.

tst> create index payment_idx on payment(contr_id, id desc);

Index created.

tst> update payment set amount=amount*3 where contr_id=1;
Before statement
--- id=1, a_t(i)=1000
--- id=2, a_t(i)=500
--- id=3, a_t(i)=-1000
Update row with id=3
--- id=1, a_t(i)=1000
--- id=2, a_t(i)=500
--- id=3, a_t(i)=-3000
Current sum=-1500
Update row with id=2
--- id=1, a_t(i)=1000
--- id=2, a_t(i)=1500
--- id=3, a_t(i)=-3000
Current sum=-500
Update row with id=1
--- id=1, a_t(i)=3000
--- id=2, a_t(i)=1500
--- id=3, a_t(i)=-3000
Current sum=1500

3 rows updated.

Для реляционной БД такое поведение недопустимо

PS. А как себя поведет MS SQL? Точнее, как там разруливаются такие ситуации -- зависимость результата от порядка обработки
Или ты просто никогда не задумывался над этим?
А Оракл за тебя подумал
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39223838
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вячеслав ЛюбомудровstudierenВячеслав Любомудров,Не очень понятно, почему ты мне это адресуешь

Извиняюсь, я просто нажал "Ответить", а т.к. последнее сообщение было Ваше, Ваше имя и осталось. Сорри, не удалил.

Вячеслав ЛюбомудровPS. А как себя поведет MS SQL? Точнее, как там разруливаются такие ситуации -- зависимость результата от порядка обработки
Или ты просто никогда не задумывался над этим?
А Оракл за тебя подумал
Да там Все просто. Когда в одно и то же время меняете 2 и более записей (разумеется и там порядок изменений не имеет значений) и если хотя бы в одной записи "осечка", то сервер не даст сохранить всем изменениям. Поэтому всё работает чётко как запланировано разработчиком БД.
Да, кстати, там триггер не работает по принципу "FOR EACH ROW", там такого нет. Всё целиком, все записи одновременно. Любые изменения будут в логической таблице "Inserted", а удалённые в "Deleted". Если нужно узнать новое и удаленное значение, то выдёргиваем из этих таблиц. Как то так.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39224077
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenКогда в одно и то же время меняете 2 и более записей (разумеется и там
порядок изменений не имеет значений) и если хотя бы в одной записи "осечка", то сервер не
даст сохранить всем изменениям.
Так нет никакой "осечки". Всё отлично вставляется и модифицируется из параллельных
коннектов. Но твоё ограничение при этом - нарушается.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39237877
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую форумчан!

Вопрос № 1.
Есть поле "LastModifiedDate", где необходимо сохранить последнюю дату и время обновления каждой записи.
Если ввести новую запись, то достаточно в значение по умолчанию указать SYSDATE.
А как в триггере надо написать, чтобы ORACLE не ругался на мутирующую таблицу во время обновления записи?
Пробовал разные варианты, но почему то ORACLE ругается.

Вопрос № 2.
В MS SQL Server при обновлении записи я мог использовать CTE, что-то вроде этого:
Код: sql
1.
2.
3.
4.
5.
6.
WITH L AS (SELECT ContractID, MAX(SaleDate) LastSaleDate
    FROM Sale
    GROUP BY ContractID)
UPDATE Sale
SET Last = 1
FROM Sale S INNER JOIN L ON S.ContractID = L.ContractID AND S.SaleDate = L.LastSaleDate


Но как я понимаю, в ORACLE такое не пойдёт.
Пробовал вот так.
Код: plsql
1.
2.
3.
UPDATE Sale Sl
SET Last = 1
WHERE Sl.ContractID IN (SELECT S.ContractID FROM Sale S GROUP BY S.ContractID HAVING MAX(S.SaleDate) = Sl.SaleDate)


Работать то конечно работает, но оооооочень медленно! Разумеется запрос на обновление не самое оптимальное. Но а как ускорить / оптимизировать запрос?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39237885
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenА как в триггере надо написать, чтобы ORACLE не ругался на мутирующую таблицу во время обновления записи?RTFM DML Triggers: Correlation Names and Pseudorecords (FAQ)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254001
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Как сделать уникальным все непустые значения поля "А" в таблице "Table1" в Oracle?
В MS SQl Server можно создать уникальный индекс с фильтром. Что-то вроде этого:
Код: sql
1.
CREATE UNIQUE INDEX IX_Table1 ON Table1 (A) WHERE (A Is Not Null);


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

Спасибо заранее.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254002
studieren,
просто создай уникальный индекс. и всё. работать будет именно так, как ты хочешь:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
create table b$m_test (id number);
-- Table B$M_TEST created.
CREATE UNIQUE INDEX b$m_test_u_indx ON b$m_test (id);
-- Unique index B$M_TEST_U_INDX created.
insert into b$m_test(id) values(1);
-- 1 row inserted.
insert into b$m_test(id) values(2);
-- 1 row inserted.
insert into b$m_test(id) values(null);
-- 1 row inserted.
insert into b$m_test(id) values(null);
-- 1 row inserted.
insert into b$m_test(id) values(null);
-- 1 row inserted.
insert into b$m_test(id) values(1);
ORA-00001: нарушено ограничение уникальности (CDS.B$M_TEST_U_INDX)

select * from b$m_test;

 ID
----
   1
   2
NULL
NULL
NULL

-- 5 row(s) selected
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254009
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эх,

Прошу прошения я неправильно написал. У меня в реальной базе индекс состоит из 2 полей.
Код: sql
1.
CREATE UNIQUE INDEX IX_Table1 ON Table1 (A, B) WHERE (A Is Not Null);


Поле "B" обязательное, поэтому там пустое значение не может быть.
Не думал, что ORACLE допускает ввод пустых значений, если индекс состоит из одного поля.
Может мне создать "Function-based index", где конкатенирую 2 поля и полученное значение попробую сделать уникальным?
Сейчас попробую.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254013
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эх,

Вроде бы получилось! :)
Спасибо за подсказку.
Правда получился дурацкий индекс, которого не буду использовать в запросах. Он будет служить только как ограничение.

Ну а если у гуру есть более продвинутая идея, буду рад любым подсказкам.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254019
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenболее продвинутая идея
Код: plsql
1.
2.
3.
alter table table1 add b_when_a_is_not_null /*invisible*/ generated always as (nvl2(a, b, null)) virtual;
alter table table1 add unique(a, b_when_a_is_not_null);
select * from table1 where b_when_a_is_not_null = …
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254030
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,

Thank you very much!
Работает однако! Взял на вооружение. :)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254135
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenКак сделать уникальным все непустые значения поля "А" в таблице "Table1" в Oracle?
В MS SQl Server можно создать уникальный индекс с фильтром. Что-то вроде этого:
Код: sql
1.
CREATE UNIQUE INDEX IX_Table1 ON Table1 (A) WHERE (A Is Not Null);

После этого сервер не позволяет дублировать НЕ пустые значения. А вот если поле "А" не заполнено пользователем, то сервер сколько угодно записей может сохранить без проблем.null, он даже в mssql null. Неужели без этого условия mssql запрещает вставлять несколько null?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254372
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-studierenКак сделать уникальным все непустые значения поля "А" в таблице "Table1" в Oracle?
В MS SQl Server можно создать уникальный индекс с фильтром. Что-то вроде этого:
Код: sql
1.
CREATE UNIQUE INDEX IX_Table1 ON Table1 (A) WHERE (A Is Not Null);

После этого сервер не позволяет дублировать НЕ пустые значения. А вот если поле "А" не заполнено пользователем, то сервер сколько угодно записей может сохранить без проблем.null, он даже в mssql null. Неужели без этого условия mssql запрещает вставлять несколько null?
Да, запрещает. В принципе я согласен с таким положением дел.
Вот к примеру ORACLE также запрещает, но только если уникальный индекс состоит как минимум из 2 полей.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39254400
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

ну и в оракле вы можете и над одной колонкой сделать fbi, который обеспечит желаемое.
другое дело, что обычно атрибут такой создают обязательным и проблемы нет в принципе
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39255438
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую всех.
Очередной вопрос.
Разве в Oracle нет пустой строки ''?
Код: plsql
1.
2.
3.
select case when replace('a', 'a', '') is null then 'is null' else 'is not null' end,
    case when '' is null then 1 else 0 end
from dual;


Получается проверять длину строки на 0 не имеет смысла?
Я имею ввиду вот такое сравнение:
Код: sql
1.
IF LENGTH(A) = 0 THEN
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39255448
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Читай документацию - узнаешь гораздо больше, чем методом тыка или форумяния.
RTFM Nulls (FAQ)
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39255819
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenПолучается проверять длину строки на 0 не имеет смысла?
Я имею ввиду вот такое сравнение:
Код: sql
1.
IF LENGTH(A) = 0 THEN



Примите в расчет - здесь вам не BSTR.
Проблема не там, где length вернет Null вместо ожидавшегося вами 0,
а, наоборот, вовсе там, где он трудолюбиво займется вычислениями ее длины для непустой строки.

В отличии от BSTR, где length просто читает префикс строки, здесь вы наступаете на алгоритм сложности порядка длины строки,
с коэффициентом на алгоритм определения длины следующего символа для кодировок типа utf8.

Просто выбросьте из головы length до тех пор, пока он вам жизненно не понадобится.
А в оставшихся случаях пользуйтесь им предельно экономно, т.к. вы точно знаете, что вы за рамками BSTR.

studierenПриветствую всех.
Очередной вопрос.
Разве в Oracle нет пустой строки ''?
Код: plsql
1.
2.
3.
select case when replace('a', 'a', '') is null then 'is null' else 'is not null' end,
    case when '' is null then 1 else 0 end
from dual;



Нет в том смысле, в каком ее длина ожидается равной нулю.
Так же, как симметрично, нет строкового +, обращающего в Null результат, если один из операндов Null.
Конкатенация всегда работает как &.

В документации тщательно оговаривается возможность изменения поведения в будущем.
Имхо, даже если так, то будущая вероятная "опасность" подстерегает только злоупотребляющих ANSI-формулировками для имен типов.
Не могу сказать, что таких борцов за переносимость не может быть, но своими глазами не только видел,
но искренне надеюсь уже и не увидеть.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39257200
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очередная проблема.

Есть поле в SQL Server varchar(8000). Т.к. в ORACLE максимальная длина 4000, пришлось мне создать 2 поля с типом данных Varchar2(4000). Далее, создал виртуальное поле, которое соединяет эти поля.
Но не тут то было. Оказывается при конкатенации ORACLE всё равно ругается, если общая длина строк превышает 4000.
Как мне быть? Есть способ как то обойти данное ограничение?

Спасибо заранее.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39257209
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenКак мне быть?
Use CLOB, Luke!
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39257212
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

на 12c нет лимита 4000 байт на varchar2 столбцах
на серверах < 12с есть, например, тип CLOB

короче, Как мне быть? читайте..
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39257213
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Спасибки! Вроде бы получилось.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39260289
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемые форумчани, у меня снова возникла проблема.
Есть простейший запрос в MS SQL Server, необходимо перевести его в ORACLE:
Код: sql
1.
2.
3.
SELECT A, B,
SUBSTRING((SELECT ', ' + SalePointCode FROM Table2 T2 WHERE T1.ID = T2.ID FOR XML PATH ('')), 3, 8000) AS SPC
FROM Table1 T1


Что делает этот запрос?
Допустим "Table1" главная таблица, а "Table2" подчинённая. Подзапрос (отмеченный красным цветом) перечисляет через запятой все коды торговых точек в одной так сказать "ячейке".
Как это сделать в ORACLE? Мне бы синтаксис.
Хотел погуглить, но не знаю как объяснить гуглу что хочу искать. :)
Попробовал искать "конкатенация", но гугл даёт совсем не то, что хочу. :(
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39260298
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenперечисляет через запятой все коды торговых точек в одной так сказать "ячейке".RTFM LISTAGG
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39260401
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,

Thanks!!!
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261596
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очередной вопрос.

В начале я создал юзера, чтобы создать параллельно схему что-то вроде этого:
Код: plsql
1.
CREATE User dbo IDENTIFIED EXTERNALLY;


Создал несколько объектов для данной схемы.
А как добавить пароль юзеру "dbo"? Как я понимаю, я могу удалить юзера и заново создать так как надо. Но его удалить мне не нужно, т.к. я потеряю все его объекта. Можно ли добавить пароля не пересоздав юзера в ORACLE?
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261642
studierenМожно ли добавить паролячтоб добавить пароля, нужно кодить до ... прочесть sqlя
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261661
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenне пересоздавВ этом грёбаном MS нет ALTER?!
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261676
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то про ALTER USER не подумал. Сорри.
Получилось.
Код: plsql
1.
alter user dbo identified by 12345678


Только вот при подключении ругается
ORA-01045: user lacks CREATE SESSION privilege; logon denied
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261686
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenuser lacks CREATE SESSIONИ GRANT-а тоже нет?!
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261711
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,

А что надо написать вместо "X" и "Y"?
Код: sql
1.
alter user dbo grant connect THROUGH X WITH ROLE Y;


Что означает здесь "X"?
А как узнать какие роли есть в базе? Как-нибудь список можно вытащить?
Я ещё не успел создать.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39261722
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Форумом Oracle не выучишь. Читай документацию, наглец.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39287838
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую форумчан!

Я в MS SQL Server при обновлении UPDATE использовал FROM, а там и INNER JOIN. Вот примерчик:
Код: sql
1.
2.
3.
4.
5.
UPDATE Table1
Set Field1 = T2.Field1
FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
    LEFT JOIN Table3 T3 ON ...
WHERE ... (здесь условия для фильтра данных)


Увы, в ORACLE такая конструкция не работает. Попробовал вот так.
Код: plsql
1.
2.
3.
4.
5.
UPDATE (SELECT T1.Field1, T2.Field1 X
    FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
        LEFT JOIN Table3 T3 ON ...
    WHERE ... )
SET Field1 = X


Вроде бы работает, но на практике оказалось, что чрезвычайно капризная конструкция. Часто ругается, что не может так.
Приходится выкручиваться вот таким образом:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
UPDATE Table1 T
SET Field1 = (SELECT T2.Field1
    FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
        LEFT JOIN Table3 T3 ON ...
   WHERE ... )
WHERE EXISTS (SELECT T2.Field1
    FROM Table1 T1 INNER JOIN Table2 T2 ON T1.ID = T2.ID
        LEFT JOIN Table3 T3 ON ...
   WHERE ... )


Конечно работать то работает, но у меня в таблице порядка больше миллиона записей, поэтому "двойной" подзапрос, т.е. и в SELECTе, и в WHERE работает невозможно медленно! Просто невыносимо! То, что в MS SQL Server обновляется буквально за 5-10 минут, в ORACLE уходит часы.
Может есть идея как-нибудь улучшить запрос на обновление? Оптимизировать как-то? Есть ещё какая-нибудь более лучшая конструкция?

Спасибо заранее.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39287848
мердж
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
studierenна практике оказалосьне надоело делать абы как, методом тыка разве что дети родятся. Но их ведь еще вырастить надо.
С 2010, задавая "Вопросы начинающего" уже можно было освоить документацию.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39287856
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenЕсть ещё какая-нибудь более лучшая конструкция?
MERGE
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39288056
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Спасибки! Реально помогло.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373703
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Прошу прощения, что опять задаю вопрос про MERGE.
Как с помощью MERGE удалить записи, но при этом не обновлять записи?
Вот здесь FAQ есть такой примерчик:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
MERGE INTO person p
   USING (   SELECT tabn, name, age FROM person1) p1
   ON (p.tabn = p1.tabn)
   WHEN MATCHED THEN UPDATE SET p.age = p1.age     
     DELETE WHERE (p1.tabn = 18)
   WHEN NOT MATCHED THEN INSERT (p.tabn, p.name, p.age)
    VALUES (p1.tabn, p1.name, p1.age)


Но мне не нужно обновлять. Попробовал убрать "UPDATE SET ...". ORACLE ругается:
ORA-00905: missing keyword
Прочёл несколько раз документацию, но так и не понял как надо правильно написать.
Вот так не получается.
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Тут_название_таблицы T USING
(SELECT ...
FROM ...
WHERE ...) U ON (тут условие)
WHEN MATCHED THEN 
  DELETE WHERE (а здесь условие удаления записи);
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373714
Vint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,
delete. не надо забивать микроскопом гвозди. удаляй предназначенным для этого инструментом.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373716
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот здесь 12105899 пишут, что DELETE без UPDATE не бывает. Печально!
Ну выкрутился так:
Код: plsql
1.
2.
3.
4.
5.
6.
MERGE INTO Тут_название_таблицы T USING
(SELECT ...
FROM ...
WHERE ...) U ON (тут условие)
WHEN MATCHED THEN UPDATE SET T.Любое_поле = T.Любое_поле
  DELETE WHERE (а здесь условие удаления записи);


Т.е. включил бестолковую инструкцию "UPDATE SET T.Любое_поле = T.Любое_поле" и вроде бы заработало.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373718
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vintstudieren,
delete. не надо забивать микроскопом гвозди. удаляй предназначенным для этого инструментом.
А как удалить данные сравнивая 2 таблицы? Конечно можно в условие WHERE EXISTS как-нибудь включить подзапрос, но тогда работает оооооочень медленно.
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373719
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studieren,

Жги дальше. Жду вопросов на автофоруме "Раньше у меня был ваз 2104, и я чистил карбюратор ветошью. Как почистить ветошью инжектор?"

MERGE statement
Specify the DELETE where_clause to clean up data in a table while populating or updating it. The only rows affected by this clause are those rows in the destination table that are updated by the merge operation
...
Рейтинг: 0 / 0
Перевод из MS SQL Server в ORACLE
    #39373721
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
studierenА как удалить данные сравнивая 2 таблицы?

Завести признак удаления и обновлять по известному тебе правилу.
...
Рейтинг: 0 / 0
120 сообщений из 120, показаны все 5 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Перевод из MS SQL Server в ORACLE
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]