Что такое код ora_columnname


Содержание

Linux.yaroslavl.ru

Учебник РНР
Назад Вперёд

Ora_ColumnName — получает имя результирующего столбца Oracle.

Описание

string Ora_ColumnName (int cursor, int column)

Возвращает имя поля/столбца column в курсоре cursor . Имя возвращается буквами верхнего регистра. Столбец 0 это первый столбец.

Динамические SQL-запросы Oracle для ускорения выборок данных

Типичная задача при работе с базами данных – выбрать информацию из разных таблиц, отфильтровать ее по определенным критериям, потом обработать и/или выдать пользователю для просмотра и визуального анализа. Если параметры отбора записей имеются в наличии и определены – эта задача решается тривиально, с помощью обычного оператора sql “select… from… where…” — где набор условий, располагаемых после where, всегда определен. Однако, бывают случаи, когда набор параметров отбора данных определяется только перед самим отбором — а изначально, во время проектирования программы, не известен.
Например, надо выбрать клиентов, “засветившихся” в базе данных торговой фирмы за определенный срок; или сделавших покупки на сумму больше некоторой заданной.
Или приходится искать конкретного человека, используя частично известные анкетные данные…
Ситуация усложняется еще больше, если для определения, какие записи нужно выбрать, а какие нет, надо вызывать какую-нибудь функцию, реализующую сложные и ресурсоемкие вычисления. Разумеется, эту функцию без необходимости лучше в обработку не включать…

Все перечисленные проблемы можно решить с помощью динамического sql.
Динамический sql позволяет строить текст запроса непосредственно внутри кода pl/sql — и затем выполнять его. Соответственно, разработчик может построить текст запроса, включая в него только необходимые, задействованные в текущий момент условия (случай, когда текст sql-запроса может быть сформирован внутри клиентского приложения, рассматривать не будем — всегда существуют ситуации, когда этого нельзя сделать по каким-нибудь причинам).

За работу с динамическими sql -запросами отвечает пакет dbms_sql. В общем, работа с ним происходит по следующей схеме.
1. Строится сам текст запроса с метками для параметров. Текст запроса может быть представлен в виде строки или коллекции строк.
2. Функцией dbms_sql.open_cursor выделяется идентификатор курсора, который будет использоваться для работы с запросом. Идентификатор ссылается на внутреннюю структуру oracle, определяющую курсор. Этот идентификатор используется процедурами пакета dbms_sql.
3. Выполняется разбор текста запроса. dbms_sql.parse.
4. Устанавливаются значения параметров запроса. dbms_sql.bind_variable.
5. Если запрос возвращает данные, то определяются столбцы и буферные переменные, в которых будут размещаться возвращаемые данные. dbms_sql.define_column.
6. Запрос выполняется. dbms_sql.execute.
7. Если запрос возвращает данные, то производится выборка данных из курсора и необходимая их обработка. dbms_sql.fetch_rows, dbms_sql.column_value.
8. Курсор закрывается. dbms_sql.close_cursor.

Ниже мы рассмотрим пример использования динамического sql для поиска человека по (неполным) анкетным данным.

Вначале определимся с используемыми структурами данных.

Поля таблицы personparticulars:

· id – уникальный номер анкетных данных
· family – фамилия
· firstname – имя
· middlename – отчество

Процесс получения результатов разобьем на две части: построение текста sql-запроса и, собственно, его выполнение. Можно оформить это как две хранимые процедуры, можно как одну — пусть разработчик сам решает. Текст sql-запроса можно формировать как в одну строку, так и в виде коллекции — на случай, если текст окажется слишком длинным. В нашем случае будем использовать коллекцию — несмотря на то, что длина текста запроса будет небольшой. Зачем? А просто так, для примера.
Условимся также, что в хранимую процедуру будут передаваться следующие параметры, управляющие поиском:

· familyfilter – шаблон для поиска по фамилии
· firstnamefilter – шаблон для поиска по имени
· middlenamefilter – шаблон для поиска по отчеству

Если в качестве какого-либо из параметров передано значение null – этот параметр при поиске игнорируем.
Результаты поиска вернем в виде таблицы в памяти. Для простоты — это будут просто номера найденных людей (значения их id).

Надеюсь, основные идеи понятны?
Дальше – сами ��

Life in Oracle

24 янв. 2015 г.

Новые возможности в динамическом SQL в Oracle 12c (возврат «неявного» курсора)

В некоторых СУБД есть возможность вернуть из хранимой функции непосредственно набор данных. Например, в СУБД MS SQL Server возможен такой код хранимой процедуры на T-SQL: Далее, клиентские библиотеки, на стороне приложения, могут такой «неявный» курсор прочитать.

Как вы хорошо знаете, такой возможности в СУБД Oracle Database нет: хранимая процедура не может вернуть просто запрос. Необходим возврат ссылки на курсор (ref cursor): через OUT-переменную, либо как результат возвращаемый хранимой функцией.

В общем-то, отсутствие в СУБД Oracle Database возможности вернуть из хранимой процедуры просто курсор, никак не мешала разработчикам приложений.
Тем не менее, это значительно усложняло процедуру миграции приложений на СУБД Oracle Database, с тех СУБД, где такая возможность присутствовала.

В СУБД Oracle Database 12c такая возможность появилась!
Это, конечно, потребовало адаптации клиентских библиотек доступа в Oracle Client. Начиная с Oracle Database Client 12c приложения, которые используют любой интерфейс доступа к СУБД (Oracle Call Interface, ODP.Net, JDBC), могут получать из СУБД такие «неявные» курсоры. Собственно на стороне СУБД, чтобы вернуть такой курсор, необходимо использовать новую процедуру RETURN_RESULT из пакета DBMS_SQL.

Эта процедура перегружена, и присутствует в двух вариантах:

  • для возврата слаботипизированной ссылки на курсор —
    PROCEDURE RETURN_RESULT(rc IN OUT SYS_REFCURSOR, to_client IN BOOLEAN DEFAULT TRUE);
  • для возврата курсора отрытого с помощью динамического SQL в пакете DBMS_SQL —
    PROCEDURE RETURN_RESULT(rc IN OUT INTEGER, to_client IN BOOLEAN DEFAULT TRUE);

Параметр to_client определяет возможность возвращения курсора непосредственно сразу клиентcкому приложению, либо в другую хранимую процедуру PL/SQL. Хранимая процедура может вернуть таким образом не один курсор, а несколько — может вызвать процедуру RETURN_RESULT несколько раз. Определим хранимую процедуру, которая возвращает курсор подобным образом в клиентское приложение: Попробуем вызвать нашу процедуру в среде утилиты SQL*Plus: Как Вы можете убедиться: утилита SQL*Plus версии 12с «понимает» такой вид курсора, и просто выводит его содержимое на свою консоль.
Эта возможность появилась в версии 12с этой утилиты. Если курсор возвращается таким образом из динамического SQL, то чтобы его получить внутри вызываемого блока PL/SQL, предназначена еще одна новая процедура пакета DBMS_SQL — GET_NEXT_RESULT. Эта процедура также перегружена и имеет два варианта:

  • для получения слаботипизированной ссылки на курсор —
    PROCEDURE GET_NEXT_RESULT (c IN INTEGER, rc OUT SYS_REFCURSOR);
  • для получения курсора отрытого с помощью динамического SQL в пакете DBMS_SQL —
    PROCEDURE GET_NEXT_RESULT (c IN INTEGER, rc OUT INTEGER);;

Для того чтобы, иметь возможность получения таких «неявных» курсоров, вызов процедуры OPEN_CURSOR должен быть выполнен с новым параметром treat_as_client_for_results равным значению TRUE, по умолчанию значение этого параметра равно FALSE. Немного перепишем нашу процедуру test_dyn3 указав в функции возврата курсора значение параметра to_client равным FALSE: Теперь вызовем нашу процедуру через динамический SQL, и попробуем получить и вывести на экран содержимое курсора: Мы рассмотрели еще одну новую возможность Oracle Database 12c в области динамического SQL — возможность непосредственного возврата курсоров из хранимых процедур.
На мой взгляд, эта новая возможность в основном востребована при миграции приложений с других СУБД, которые уже поддерживают эту технологию, на СУБД Oracle Database. Поскольку в этом случае значительно снижается объем работ по адаптации кода приложения под СУБД Oracle.

Изменение соединения

Эта статья посвящена «хитрым» операторам UPDATE , изменяющим данные в одной таблице на основе данных из другой. Попутно обсуждаются причины возникновения ошибки ORA-01779 при выполнении таких действий путем изменения соединения. По мотивам очередного ответа Тома Кайта .

Оператор UPDATE и NULL-значения

При изменении столбца с помощью оператора update , значение некоторых записей (которые не надо менять) изменяется на NULL . Я использую следующий оператор:

В результате выполняются все необходимые изменения, но изменяются и записи, которые не надо менять: они получают значения Null . Можно ли этого избежать, поскольку нам надо часто изменять записи, но не все сразу.

Нет ли способа изменить только те записи, которые нужно, и не сбросить значения в других записях в Null ?

Ответ Тома Кайта

Есть как минимум 2 способа правильно выполнить такого рода коррелированное изменение. Я покажу свой любимый метод (изменение соединения) и другой метод, который будет работать если нельзя задать ограничение уникальности по LOOKUP(keyname) (что необходимо для успешного изменения соединения).

Рассмотрим следующие тестовые таблицы:

А вот параметр » other_value «, который вы используете в своем операторе update .

Далее мы изменяем соединение. Можно изменять значение столбцов только в одной из таблиц, а другие таблицы, которые мы не изменяем, должны быть «защищены ключом» — мы должны иметь гарантию, что при соединении NAME со второй таблицей будет возвращено не более одной записи. Для этого столбец keyname в таблице LOOKUP должен быть либо первичным ключом, либо быть связанным ограничением уникальности.

Обратите внимание, изменилась только интересующая нас строка — остальные данные не затронуты.

Следующий способ сработает безо всяких ограничений — не нужно первичного ключа млм ограничения уникальности для таблицы lookup (но лучше точно знать, что подзапрос вернет 0 или 1 запись!).

Оператор очень похож на ваш update , но имеет конструкцию where , чтобы изменялись только строки, для которых есть соответствия.

А можно ли добиться того же для нескольких столбцов?

Мне не удалось сделать следующее. Я создал две таблицы t и t1 с помощью select * from user_objects . В таблицах t и t1 — по 117 записей. Затем я взял один object_name(PRIMARY_SALESFORE) в таблице t и изменил три записи — object_type , object_id и created .

Теперь при попытке изменить эти три поля в таблице t на основе t1 я получаю следующее сообщение об ошибке. Что я делаю не так?

При попытке изменить всего один столбец в T я тоже получаю сообщение об ошибке:

Ответ Тома Кайта

Таблицы T и T1 «невидимы» за пределами подставляемого представления (inline view). Вы это исправили, добавив псевдонимы toid , t1oid .

Что касается второй ошибки, пожалуйста, перечитайте представленный выше ответ. НАДО, чтобы столбец object_id таблицы T1 был связан ограничением первичного ключа/уникальности, чтобы каждая строка таблицы T соединялась НЕ БОЛЕЕ, чем с одной строкой таблицы T1 .

Пусть в таблице T имеется:

что должно быть в результате:

надо ли при соединении брать 123 или 456, и в каких случаях? Поскольку результат этого изменения на 100% НЕОДНОЗНАЧНЫ, мы его не допускаем. Необходимо гарантировать защиту ключом с помощью ограничения первичного ключа/уникальности.

Соответствующий индекс в любом случае нужен из соображений производительности.

Комментарий читателя от 2 апреля 2002 года

Спасибо, Том. Я знал, что если еще раз (внимательно) перечитаю твой ответ, то смогу найти ошибку в SQL-операторе. Но, в любом случае, не мог бы ты помочь мне добиться желанной цели — изменить три столбца из другой таблицы, имеющий один совпадающий столбец ( object_name ), уникальный, но не являющийся первичным ключом.

Ответ Тома Кайта

Этот запрос позволит решить вашу проблему. Если нельзя задать ограничение уникальности (которое нужно ТЕОРЕТИЧЕСКИ, даже если не потребуется практически — если значения в столбце some_field таблицы t2 окажутся НЕ уникальными, представленный запрос закончится сообщением об ошибке «подзапрос вернул более одной строки», потому что оператор update будет НЕОДНОЗНАЧНЫМ)

Хороший прием. Комментарий читателя от 9 апреля 2002 года

Спасибо за прекрасный сайт. Я пытаюсь изменить таблицу на основе определенной информации в той же таблице. Запрос выглядит следующим образом:

Предполагается, что условию WHERE курсора C1 будет удовлетворять 9 миллионов строк. Мой АБД говорит, что транзакция будет зафиксирована только после изменения 9 миллионов строк, и мне надо фиксировать ее после каждых 50000 — правильно ли это?

Что можно сделать, чтобы это изменение выполнялось быстрее — я знаю, что ты ненавидишь такие вопросы, если за ними не стоят определенные критерии, но что, если я создам индекс (по функции)?

Ответ Тома Кайта

Я лично делал бы так:

Если бы по столбцу position_id был индекс, я бы его удалил, выполнил изменение и пересоздал индекс без возможности восстановления и с распараллеливанием.

Прежде чем вы скажете: «но там же 9 миллионов строк — надо фиксировать по частям», я отвечу — ни в коем случае. Проверьте только, что выделено достаточно сегментов отката (иначе, при использовании вашего подхода, РАНО ИЛИ ПОЗДНО, вы получите сообщение об ошибке ORA-01555 — поищите на сайте обсуждения по слову 01555 или 1555 и поймете, что я имею ввиду).

Потребуется не так уж много места в сегментах отката, как может показаться. Процедурный код, вроде вашего:

  • будет работать медленне простого оператора update
  • сгенерирует больше данных отмены и повторного выполнения, чем один оператор update
  • будет источником ошибок ( ora-01555 , другие логические ошибки)
  • у вас уже есть логическая ошибка — c1%rowcount не содержит «суммарное» значение; это колчиество строк, измененных последним оператором update . Если вы измените фактически менее 50000 строк одним оператором, транзакция не будет зафиксирована (в вашем коде — ошибка)
  • вообще — плохая идея.

В своей системе я только что изменил 1099008 строк:

для этого потребовалось около 100 Мбайт в сегменте отката. Вам следует ожидать порядка гигабайта. Я бы просто убедился (с помощью АБД), что столько места есть, использовал бы оператор set transaction use rollback segment при необходимости (можно просто создать временный сегмент для этого оператора update в каталоге /tmp , например, и потом его удалить). Выполните update . Этого достаточно.

Меньше думать, меньше делать, меньше вероятность ошибки.

Комментарий читателя от 30 апреля 2002 года

В какой версии Oracle появилась возможность выполнять «изменение соединения»? Я всегда использовал для таких запросов второй вариант, с конструкцией EXISTS . Всегда казалось смешным, что приходится один и тот же подзапрос вводить дважды.

Тебе надо написать книжку о хитрых приемах в Oracle SQL.

Ответ Тома Кайта

Уверен, что эта возможность появилась в версии 7.3

Параллельные операторы ЯМД и изменение представления с соединением

В представленном выше запросе, который демонстрирует изменение представления с соединением, меня интересует, выполняется ли это изменение параллельно, если таблица t фрагментирована и выполнен оператор alter session enable parallel dml . Я использую аналогичный оператор update и выяснил, что лучшим планом выполнения оператора select будет полный просмотр обеих таблиц и соедитнение хешированием.

Ответ Тома Кайта

Если удовлетворены все остальные критерии (включено распараллеливание, таблицы допускают «распараллеливание») — должно выполняться параллельно.

Изменение будет выполняться по фрагментам таблицы T , с полным просмотром каждого фрагмента T и соединением его с таблицей T1 после фильтрации по условию upper(t.object_name) .

Один из способов убедиться в этом — выполнить изменение, а затем — оператор select * from t where rownum = 1; Если этот оператор сработает, изменение не распараллеливалось, а если нет — было выполнено параллельно. Выполните Commit и сможете выбирать данные.

Можно ли это сделать, если задействовано более двух таблиц?

Я делал это, когда в соединении задействовано две таблицы.

Можно ли это сделать, если необходимо изменить столбец таблицы A в соответствии со значениями столбца в таблице C . Таблицы связаны так: A -> B -> C , где A является главной для всех, а B — главной для C ?

Ответ Тома Кайта

Ай-я-яй, такой простой пример — вы же все уже указали — и не попытаться сделать. Ладно.

Ответ — да, если соблюдается «защита ключом», другими словами, каждая строка таблицы A появится в результате соединения НЕ БОЛЕЕ ОДНОГО РАЗА. В противном случае — нет.

Рассмотрим простой пример:

Блокировки. Комментарий читателя от 2 октября 2002 года

будут ли обе таблицы, name и lookup , заблокированы по ходу изменения?

Ответ Тома Кайта

Блокируются только строки таблицы, которую вы изменяете.

Комментарий читателя от 29 января 2003 года

какой из этих двух запросов лучше с точки зрения производительности? Я предполагаю, что первый, но сомневаюсь. Если я ошибаюсь, то почему?

Ответ Тома Кайта

Нет, первый лучше

Хотя, постойте, второй лучше

Оба могут работать быстро, я думаю.

Их производительность будет зависеть от используемого оптимизатора, актуальности статистической информации, и т.п.

В общем случае, если » NAME » — очень маленькая таблица, а » LOOKUP » — очень большая, (но проиндексированная по keyname / othercolumn ) — оператор с where exists вполне можно использовать.

Но обычно лучше изменять соединение.

Изменение главной таблицы на основе подчиненной (подчиненная — с составным ключом)

Не мог бы ты помочь мне сделать то, что я пытаюсь — изменить 2 или более столбца главной таблицы на основе данных в подчиненной, у которой первичный ключ — составной.

В результате изменения надо установить значения столбцов calorie , fibre и total_fat в таблице food_table равными значениям в таблице food_portion , где food_portion.qty = 100 и food_portion.weight = 100

Гарантируется, что для каждого food_id в таблице food_portion будет только одна строка с qty = 100 и weight = 100 (т.е. оператор select food_ > вернет ровно одну строку для каждого значения food_id )

Я выполнял следующий оператор update :

Но получил сообщение об ошибке ‘ORA-01779: cannot modify a column which maps to a non key-preserved table’

Потом я попробовал выполнить:

И оба оператора вернули сообщение об ошибке ORA-01427: single-row subquery returns more than one row

Меня интересует, можно ли выполнить такое изменение, не используя PL/SQL?

Ответ Тома Кайта

Если вы указываете:

ORA-01427: single-row subquery returns more than one row

Значит, предположение о единственности строки для каждого food_id не оправдалось.

Но, в любом случае, если запрос:

возвращает НОЛЬ строк (нет дублирующихся значений!), то:

Выполняет соответствующее изменение.

Очень полезный пример

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

Комментарий читателя от 1 мая 2003 года

Если в твоем исходном примере вместо:

Я получаю сообщение об ошибке » ORA-01779: cannot modify a column which maps to a non key-preserved table » (см. ниже).

Разме в запросе columnName не возвращает тоже всего одну запись? Почему так не срабатывает?

Ответ Тома Кайта

А теперь, какой результат должен получиться после изменения:

Столбец value будет иметь значение x или y ?

Чтобы избавиться от двусмысленности, необходим первичный ключ по столбцам таблиц » lookup «, по которым выполняется соединение — у вас его нет.

Join the world’s largest interactive community dedicated to Oracle technologies.

Display column value as column name

I have a requirement to display column names as column values and vice versa. Pls suggest how to do this.

Test data Expected output

  • 2743 Просмотров
  • Метки: нет (добавить)
1. Re: Display column value as column name

What would you expect to get for the heading if there is more than one row of data?

You can possibly achieve it using some dynamic SQL to set the column names as you want although there’s rarely any valid reason for doing that, so perhaps you’d better explain what you’re really trying to achieve.

Another alternative is to interface into the underlying ODCI interface of oracle.
And to use it e.g.

  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
2. Re: Display column value as column name
  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
3. Re: Display column value as column name

And where is the output expected? In SQL*Plus? or within PL/SQL code?

Clarify your requirements and tell us what database version you are using.

  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
4. Re: Display column value as column name
  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
5. Re: Display column value as column name
  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
6. Re: Display column value as column name
  • Мне нравится Показать отметки «Мне нравится» (0) (0)
  • Действия
7. Re: Display column value as column name

Ok, I’ve only got 10g here at the minute, so this is what I’d do.
Now, with 11g you can actuall create the DBMS_SQL cursor from the top part of the code.
And using the new function in 11g’s DBMS_SQL package called dbms_sql.to_refcursor and convert the DBMS_SQL cursor to a REF CURSOR which you can then use in your applications (if that’s the way you need to go).

Whatever route you take though, you won’t do this simply in SQL as the column names of a query are required to be known before any data is retrieved when a query (cursor) executes. You can see that when you use the DBMS_SQL package, where the query has to be parsed and the column names and descriptions are determined before any fetching of data.

Блок PL/SQL

При компиляции, Oracle выдаёт ошибку » PLS-00402: alias required in SELECT list of cursor to avoid duplicate column names «. Как исправить ?

28.04.2015, 10:51

Как сделать чтобы при наведении на блок 1 скрывался навсегда блок 2
Здравствуйте! #block_1:hover #block_2 Сейчас у меня так стоит, навожу мышь на блок.

Обязательно ли нужны знания SQL для начала работы с LINQ to SQL
Привет всем! Такой вопрос: обязательно ли нужны знания SQL для начала работы с LINQ to SQL.

Получить тип столбца из таблицы в SQL Server посредством Linq to SQL
Как получить тип столбца из таблицы в SQL Server посредством Linq to SQL или используя любой.

function — Функция Oracle to hardCode Column Name в качестве параметра

У меня есть две таблицы с одинаковыми именами столбцов (52+ coulmns). Мне нужно написать функцию Oracle, чтобы сравнить, изменяются ли записи между этими столбцами. EMP_ID является основным ключом

Я пытаюсь использовать функцию ниже, но это дает мне неправильный результат, я называю funcaiton следующим образом:

Функция, которую я создал:

    2 1
  • 28 май 2020 2020-05-28 10:09:34
  • Ragav

1 ответ

in_Column_Name — строковая переменная, которой вы назначаете буквенное строковое значение, например DEPT_NAME .

Поэтому ваши запросы интерпретируют это как литеральное строковое значение и возвращают то же самое в v_table1_Column_Value .

Чтобы сделать то, что вы ожидаете, вам нужно использовать Dynamic SQL, например:

Вы должны знать о возможности SQL Injection здесь, то есть значение in_Column_Name не может быть предоставлено конечными пользователями.

Что такое код ora_columnname

109472 просмотра

10 ответа

2865 Репутация автора

Получите вышеупомянутую ошибку, когда немедленное выполнение вызывается в цикле

Вот фрагмент кода

Ответы (10)

7 плюса

19304 Репутация автора

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

6 плюса

141510 Репутация автора

Идентификаторы без кавычек должны начинаться с буквенного символа (см. Правило 6 здесь ). Вы пытаетесь присвоить значение столбцу с именем, начинающимся с цифры 1AO00 и 1AP00 т. Д.

Не видя определения таблицы, CustomersPriceGroups мы не знаем, есть ли в ней столбцы с этими именами. Если это так, то они должны быть созданы как идентификаторы в кавычках. Если это так, вам придется ссылаться на них (везде) с кавычками, что не является идеальным — делает код немного сложнее для чтения, позволяет легко допустить такую ​​ошибку и может быть трудно определить, что не так. Даже Оракул говорит, на той же странице:

Примечание. Oracle не рекомендует использовать идентификаторы в кавычках для имен объектов базы данных. Эти идентификаторы в кавычках принимаются SQL * Plus, но они могут быть недействительными при использовании других инструментов, управляющих объектами базы данных.

В вашем коде вы, кажется, используете кавычки при назначении sQ , но вывод, который вы показываете, не делает; но он также не имеет saap. идентификатора схемы. Это может быть из-за того, что вы не используете ту версию кода, о которой вы думаете, но, возможно, просто потерялись, если перепечатали данные, а не вставили их — вы не показываете более раннюю версию c.cuno . Но также возможно, что вы, например, неправильно указали название столбца.

Если execute выдает ошибку, вы не увидите команду, выполняемую в этот раз в цикле, потому что отладка идет после нее — вы видите успешные значения, а не те, которые выходят из строя. Вам необходимо проверить все значения, возвращаемые функциями; Я подозреваю, что g возвращаемое значение для cpgs этого на самом деле не является допустимым именем столбца.

Как говорит @ninesided, показ дополнительной информации, в частности полное сообщение об исключении, поможет определить, что не так.

25 плюса

2411 Репутация автора

проверьте ваш запрос на двойную запятую.

(после COLUMN2 есть лишняя запятая).

Обновление: недавно (у некоторых людей есть особые таланты) мне удается получить то же исключение с новым подходом:

(второй SET избыточен)

Автор: yurin Размещён: 21.11.2013 02:09

1 плюс

872 Репутация автора

В дополнение к причинам, приведенным здесь в других ответах, вам также может понадобиться проверить, что ни одно из имен столбцов вашей таблицы не имеет имени, которое считается специальным / зарезервированным словом в базе данных oracle.

В моем случае у меня было имя столбца таблицы uid. uid — зарезервированное слово в oracle, и поэтому я получаю эту ошибку.

К счастью, моя таблица была новой, и в ней не было данных. Я смог использовать команду Oracle DROP table, чтобы удалить таблицу и создать новую с измененным именем для столбца проблемы.

У меня также были проблемы с переименованием столбца проблемы, поскольку оракул не позволил мне и продолжал выдавать ошибки.

1 плюс

3082 Репутация автора

если вы добавите дополнительный «,» в конце оператора set вместо синтаксической ошибки, вы получите ORA-01747, что очень странно для Oracle, например

плюса

378 Репутация автора

Причина также может быть в том, что вы группируете набор столбцов, отличный от выбранного, например:

Автор: Rafał Размещён: 13.07.2020 09:04

1 плюс

458 Репутация автора

И я писал запрос, как. Я должен был удалить [ и ]

Недавно мы перешли с SQL Server на Oracle.

Автор: Jaikrat Размещён: 07.09.2020 09:17

плюса

1694 Репутация автора

Вы использовали ключевое слово oracle в своем выражении SQL

плюса

59 Репутация автора

ORA-01747: неверная спецификация user.table.column, table.column или столбца

Вы получите, когда пропустите отношение столбца, когда вы сравните оба идентификатора столбца, и ваш идентификатор не будет одинаковым. Проверьте оба идентификатора в вашей базе данных. Вот пример примера, с которым я столкнулся:

Здесь вы получите сообщение об ошибке, когда ‘CHECK_CONDITION’ и ‘ID’ оба идентификатора столбца не будут одинаковыми. Если оба идентификатора будут одинаковыми, на этот раз ваш запрос будет выполнен нормально, проверьте идентификаторы обоих столбцов, которые вы сравниваете в своем коде.

плюса

599 Репутация автора

Для меня проблема была связана с использованием имени столбца «CLUSTER», которое является зарезервированным словом в Oracle. Я пытался вставить в колонку. Переименование столбца исправило мою проблему.

Ошибки Оракла ORA-00000 — ORA-00999

Группы первой тысячи ошибок Oracle (по диапазонам кодов от 0 до 999):

Сообщения об ошибках ORA-00000 — ORA-00099

Сообщения ORA-00000 — нормальное, успешное завершение, т.е., не ошибка.

Методологические ошибки доступа к ядру 0001-0049

  • ORA-00001: Дублированный ключ в индексе
  • ORA-00017: Превышено максимальное число вызовов
  • ORA-00018: Превышено максимальное количество сеансов
  • ORA-00019: Число сеансов превысило число лицензий
  • ORA-00020: Превышено максимальное число(количество) процессов (num)
  • ORA-00021: Сеанс занят другим процессом. Не переключайте сеанс
  • ORA-00022: Неверный > Ошибки управления входом в БД Оракл и выходом из неё:
  • ORA-00300: Недопустимый размер блока журнала повторного выполнения, указанный размер [значение] превышает предел размер [значение]
  • ORA-00301: Ошибка в добавлении файла протокола [значение] — файл не может быть создан
  • ORA-00302: Превышен лимит количества журнальных файлов
  • ORA-00303: невозможно выполнить Parallel Redo
  • ORA-00304: Запрашиваемый INSTANCE_NUMBER занят
  • ORA-00305: Журнал [значение] потока [значение] не согласован и принадлежит другой базе данных
  • ORA-00306: Достигнут предел количества экземпляров [значение]
  • ORA-00307: Запрошенный INSTANCE_NUMBER выходит за допустимые пределы, максимум [значение]
  • ORA-00308: Невозможно открыть архивный журнал [значение]
  • ORA-00309: Журнал принадлежит другой базе данных
  • ORA-00310: Архивный журнал содержит последовательность [значение]; требуется последовательность [значение]
  • ORA-00311: Невозможно прочитать заголовок архивного журнала
  • ORA-00312: Доступный журнал [значение] поток [значение]
  • ORA-00313: Ошибка при открытии файла журнальной группы [значение] поток [значение]
  • ORA-00314: Журнал [значение], ожидаемая последовательность [значение] не совпадает с [значение]
  • ORA-00315: Журнал [значение] поток [значение], неверное значение [значение] в заголовке
  • ORA-00316: Журнал [значение], значение [значение] в заголовке указывает что это не журнальный файл
  • ORA-00317: Указанный файл [значение] не является журнальным файлом
  • ORA-00318: Журнал [значение] превысил допустимый размер [значение] не совпадает с [значение]
  • ORA-00319: Журнал [значение] имеет некорректный статус сброса
  • ORA-00320: Невозможно прочитать заголовок файла [значение] потока [значение]
  • ORA-00321: Невозможно обновить данные в заголовке журнального файла [значение] поток [значение]
  • ORA-00322: Журнал [значение] потока [значение] не текуща копия
  • ORA-00323: Текущий журнал потока [значение] не пригоден к использованию и все другие требуют архивации
  • ORA-00324: Имя журнального файла [значение] переведенное [значение] слишком длинное, превышен допустимый предел [значение]
  • ORA-00325: Архивный журнал потока [значение] содержит неверное значение [значение] в заголовке
  • ORA-00326: Журнал начинается на [значение], требуется ранее измененное [значение]
  • ORA-00327: Журнал [значение] потока [значение] имеет физический размер [значение] меньшее чем требуется [значение]
  • ORA-00328: Архивный журнал заканчивается на [значение], требуется более позднее изменение [значение]
  • ORA-00329: Архивный журнал начинается на [значение], требуется изменение [значение]
  • ORA-00330: Архивный журнал заканчивается на [значение], требуется изменение [значение]
  • ORA-00331: Версия журнала [значение] не совместима с версией ORACLE [значение]
  • ORA-00332: Архивный журнал очень маленький, возможно неполностью заархивирован
  • ORA-00333: Журнал повторного выполения прочитал [значение] ошибочных блоков из доступных [значение]
  • ORA-00334: Архивный журнал [значение]
  • ORA-00335: Доступный журнал [значение]: Нет журнала с таким номером, журнал не существует
  • ORA-00336: Размер блока файла журнала меньше чем минимальный блок [значение]
  • ORA-00337: Журнальный файл [значение] не существует и размер не указан
  • ORA-00338: Журнал [значение] больше чем последнее значение управляющего файла
  • ORA-00339: Архивный журнал не содержит каких либо повторных исполнений
  • ORA-00340: I/O ошибка при обработке журнала [значение] потока [значение]
  • ORA-00341: Журнальный файл [значение] имеет неверный номер [значение] в заголовке
  • ORA-00342: Архивный журнал не содержит информации SCN [значение]
  • ORA-00343: Слишком много ошибок, журнал закрыт
  • ORA-00344: Невозможно пересздать доступный журнал [значение]
  • ORA-00345: Ошибка записи в журнал повторного исполнения, блок [значение] всего [значение]
  • ORA-00346: Журнал отмечен как устаревший (STALE)
  • ORA-00347: Журнал [значение] потока [значение] имеет размер блока [значение], не совпадает, должно быть [значение]
  • ORA-00348: Неудачная обработка повторного восстановления, экземпляр должен быть остановлен
  • ORA-00349: Отказ в получении размера блока для [значение]
  • ORA-00350: Журнал [значение] (поток [значение])экземпляра [значение] требует архивирования
  • ORA-00351: Неправильное время для восстановления
  • ORA-00352: Все журналы из потока [значение] должны быть архивированы — нельзя разрешить
  • ORA-00353: Поврежден журнал блок [значение] изменение [значение] время [значение]
  • ORA-00354: Поврежден заголовок блока журнала повторного выполнения
  • ORA-00355: Номер изменения за пределами последовательности
  • ORA-00356: Неверная длина описания изменения
  • ORA-00357: Слишком много членов указано для журнального файла, максимум [значение]
  • ORA-00358: Слишком много членов указано, максимум [значение]
  • ORA-00359: Группа журнальных файлов [значение] не существует
  • ORA-00360: Не член журнального файла: [значение]
  • ORA-00361: Невозможно удалить последний журнал [значение] из группы [значение]
  • ORA-00362: Требуемый член является верным журнальным файлом в группе [значение]
  • ORA-00363: Журнал не архивированный
  • ORA-00364: Невозможно писать в заголовок нового журнала
  • ORA-00365: Указанный журнал не корректный
  • ORA-00366: Журнал [значение] потока [значение], ошибка контрольной суммы в заголовке файла
  • ORA-00367: Ошибка контрольной суммы в заголовке файла
  • ORA-00368: Ошибка контрольной суммы в блоке журнала повторного выполнения
  • ORA-00369: Текущий журнал потока [значение] испорчен и другой журнал очищен
  • ORA-00371: Недостаточно памяти в разделяемом пуле, должно быть не меньше [значение]
  • ORA-00372: Файл [значение] не может быть изменен в настоящее время
  • ORA-00373: Версия открытого журнала [значение] несовместима с версией ORACLE [значение]
  • ORA-00374: Значение параметра db_block_size=[значение] некорректно; должен быть составной в диапазоне [значение..значение]
  • ORA-00375: Невозможно получить значение по-умолчанию db_block_size
  • ORA-00376: Файл [значение] не может быть прочитан в настоящее время
  • ORA-00377: Частое резервное копирование файла [значение] причина тупика в операциях записи
  • ORA-00378: Буферный кэш не может быть создан как указано
  • ORA-00379: Нет свободных буферов в буферном кэше [значение] для блока [значение]K
  • ORA-00380: Не могу указать db_[значение]k_cache_size [значение]K это стандартный размер блока.
  • ORA-00381: Невозможно использовать старый и новый параметры для указания размера буферного кэша
  • ORA-00382: %s неверный размер блока, верное значение [значение..значение]
  • ORA-00383: Значение по умолчанию для кэша не может быть уменьшено до нуля
  • ORA-00384: Недостаточно памяти для увеличения кэша
  • ORA-00390: Журнал [значение] потока [значение] очищен и не может быть текущим журналом
  • ORA-00391: Все потоки с этого момента должны переключится на новый формат журнала
  • ORA-00392: Журнал [значение] потока [значение] был очищен, операция не разрешена
  • ORA-00393: Журнал [значение] потока [значение] необходим для восстановления недоступной (offline) базы данных.
  • ORA-00394: Доступный журнал заново используется во время его архивирования
  • ORA-00395: Журнал для клона базы данных должен быть переименован
  • ORA-00396: Ошибка [значение] требует отката на однопроходное восстановление
  • ORA-00397: Восстановление экземпляра прервано с ошибкой
  • ORA-00398: Восстановление прервано до правильной переконфигурации
  • ORA-00399: Поврежденное описание изменений в журнале повторного исполнения

Настройка и управление сети Oracle

Сеть это неотъемлемая часть клиент-серверной архитектуры, которая является фундаментальное составляющей всех современных баз данных. У БД Oracle была возможность для клиент-серверных вычислений с самого начала (версия 1, выпущенная в 1978 году использовала разделение между кодом Oracle и пользовательским кодом), но только в версии 4 в 1984 году Oracle представила разделение между компьютером пользователя и сервером. Настоящая поддержка клиент-серверной архитектуры наступила с версией 5 в 1986 году. В это главе мы рассмотрим сервис Oracle Net, который раньше назывался Sqlnet и некоторые DBA до сих пор используют это название.

По умолчанию Oracle Net настроена как выделенный сервер (dedicated server). В такой конфигурации каждому пользовательскому процессу, подключенному к БД, будет создаваться свой серверный процесс. Альтернативой этой конфигурации является конфигурация разделяемого сервера (shared server), где все пользовательские процессы используют фиксированный набор серверных процессов, разделяемых между пользовательскими сессиями. DBA неохотно используют shared server архитектуру, однако знание это конфигурации необходимо.

Oracle Net – это технология позволяющая использовать клиент-серверную архитектуру Oracle. Это механизм для установки сессии с экземпляром БД. Существует несколько программ, которые могут быть использованы для настройки и управления Oracle Net, хотя можно настроить всё используя только текстовый редактор. Каким бы инструментом вы не пользовались, результатом всё равно будет набор файлов, которые управляет процессом запуска сессий listener-ом при получении пользовательского запроса и определяет каким-образом пользовательскией процесс находит listener.

Oracle Net и клиент-серверная парадигма

Пользователя и базу данных разделяет множество уровней. В окружении Oracle ни пользователи не имеют прямого доступа к базе данных, ни пользовательские процессы. Клиент-серверная архитектура гарантирует что любой доступ к БД контролируется сервером.

Пользователь взаимодействует с пользовательским процесс: это приложение которое запущено на локальной машине. Например Microsoft Acces и ODBC Driver, либо приложение написанное на C и использующее OCI библиотеки или SQL *Plus. Какое бы это ни были приложение, назначение пользовательского процесса одинаковое – позволить пользователю вводить информацию, которую приложение может использовать для генерации SQL запросов. В случае SQL *Plus пользовательский процесс будет просто ждать ввода запроса — более продвинутые инструменты могут отображать свойства объектов БД, генерировать и валидировать SQL команды, в любом случае будет сформирован SQL запрос, который передаётся серверному процессу.

Серверный процесс работает на сервере базы данных и выполняет запросы, полученные от пользовательского процесса. Это базовое клиент-серверное разделение: пользовательский процесс создаёт SQL, серверный процесс выполняет. Выполнение SQL запроса происходит в четыре этапа: разбор (parse), связывание (bind), выполнение (execute) и выборка(fetch). На этапе разбора сервер определяет валиден ли запрос, какие объекты используются и как выполнить запрос максимально быстро. Разбор использует shared pool: стурктуры памями используются для преобразования SQL в исполняемый код. На этапе связсывания – все переменные преобразуются в литералы. Этап выполнения будет использовать SGA и возможно саму базы данных. Во время выполнения данные в буфере кэша будет считываться или обновляться, изменения записываться в буфер логов, и если необходимых блоков нету в буфере серверный процесс считает их из файлов данных. Это единственный момент времени при выполнении запроса когда используется сама база данных. И, наконец, на этапе выборки серверный процесс отправит результирующий набор данных полученный в результате выполнения запроса назад пользовательскому процессу, и пользовательский процесс преобразует результат для отображения.

Oracle net предоставляет механизм для запуска серверного процесса, который будет выполнять код от имени пользовательского процесса. Этот механизм называют установкой сессии. Также Oracle Net используется для поддержки сессий: передачу SQL запросов от пользовательского процесса к серверному, и получение результатов выполнения запросов от сервеного процесса к пользовательскому.

На рисунке 4-1 отображены компоненты сессии. Пользователь взаимодействует с пользовательским процессом, пользовательский процесс в свою очередь взаимодействует с серверным процессом используя Oracle Net; серверный процесс работает с экземпляром БД и экземпляр при помощи фоновых процессов работает с базой данных. Клиен-серверное разделение осуществляется между пользовательским процессом создающим SQL запросы и серверным процессом выполняющим их. Это разделение обычно будет и физическим, так же как логическим: обычно серверные и клиентские машины соединены с помощью локальной сети, так же они могут соединяться с помощью сети интернет или вообще работать на одной физической машине. Oracle Net отвечает за установку соединения (создание сессии) и все взаимодействие между серверным и пользовательским процессом.

Установка соединения (создание сессии)

Когда пользователь хочет подключиться к БД используется команда вида

Конечно если используется инструмент с графическим интерфейсом вы не будете писать такую команду, ваше приложение просто спросит все необходимые данные для подключения и команда будет сгенерирована пользовательским процессом. Разберём эту команду. Вначале идёт имя базы данных (STORE) и пароль (ADMIN123) разделённые символом “/”. Затем идёт символ “@” после которого строка подключения “ORCL11G”. Символ “@” является идентификатором для пользовательской сессии указывающим что сетевое подключение необходимо. Если пропустить этот символ и не указывать строку подключения, тогда пользовательский процесс преполагает что экземпляр к которому вы хотите подключиться запущен на локальной машине и он всегда доступен с помощью IPC протокола. Если символ “@” и строка подключения указаны, тогда пользовательский процесс будет использовать сетевое подключение для работы с удаленной машины – хотя фактически, сервер может быть той же локальной машиной и вы будете посылать запрос и принимать одной и той же сетевой картой локальной машины.

Подключение к локальному экземпляру

Даже когда вы подключаетесь к экземпляру работающему на локальной машине, вы всё равно используете Oracle Net. Все сессии используют сетевой протокол для разделения пользовательского когда от серверного, но для локального подключения этим протоколом будет IPC: это протокол предоставляемый операционной системой который пользоляет «общаться» процессам работающим на одной машине. Это единственный вид подключения который не требудет listener-а; более того, локальное подключение не требует никакой настройки. Единственная информация которая нужна пользовательскому процессу для подключения, это к какому экземпляру БД вы хотите подключиться. Нужно помнить что могут работать несколько экземпляров на одном компьютере. Эту инфомрацию процесс получает из системных переменных. На рисунке 4-3 показан пример подключения в системе Linux, а на рисунке 4-3 отображено как подключиться к локальной базе данных в Windows

Единственным отличием будет метод установки системных переменных.

Определение имени (Name resolution)

Когда происходит попытка подключения используя Oracle Net, первым делом необходимо определить куда конкретно вы хотите подключиться. Это процесс определения имени. Если команда CONNECT содержит строку подключения “@orcl11g”, Oracle Net необходимо понять что значит “orcl11g”. Строка должна быть преобразована в определённую информацию: протокол, который будет использоваться (предположим TCP), IP адресс на котором запущен listener, порт используемый listener-ом и имя экзкмпляра БД к которому вы хотите подключиться. Можно использовать разные строки подключения: к примеру вместо IP адреса в строке подключения может указываться имя хоста, которое затем определяется в IP адресс используя DNS сервер. Вместо указания имени экземпляра может быть указано имя сервиса, которое (в RAC архитектуре) может обслуживать несколько экземпляров. В single-instance архитектуре тоже могут использоваться сервисы – к примеру для отслеживания нагрузки на базу данных разными группами пользователей. Вы можете насторить разные механизмы выделения адреса сервера и имени экземпляра из строки подключения, но так или иначи процесс определения имени должен давать пользовательскому процессе достаточно информации для нахождения listener-а и создания запроса к экземпляру.

Запуск серверного процесса

Listener базы данных, работающий на сервере, использует один или несколько протоколов для мониторинга одного или нескольких портов на одном или нескольких сетевых интерфейсах в ожидании входящих запросов на подключение. Вы можете запустить несколько listener-ов на одном сервере, а также один listener может принимать запросы на подключение для нескольких экзмепляров. Когда listener получает запрос на подключение, вначале он должен проверить доступен ли запрашиваемый экземпляр. Если экземпляр доступен, listener запустит сервеный процесс для обслуживания пользовательского процесса. Таким образом, если к вашей базе данных подключено одновременно тысяча пользователей – на сервере будет работать тысяча серверных процессов. Такая конфигурация называется архитектура выделенного сервера (dedicated server architecture). Существует возможность использования другой конфигурации, когда пользовательские сессии обслуживаются выделенным процессом диспетчером (dispatcher process), но серверные процессы разделяются между пользовательскими сессиями. Эта архитектура называется общий сервер (shared server).

При использовании TCP протокола, каждому серверному процессу запущенному listener-ом присваивается уникальный номер TCP порта. Это значение устанавливается во время запуска процесса согласно алгоритму маппинга портов вашей операционной системы. Номер порта возващается пользовательской сессии и теперь пользоватеский процесс может работать напрямую с выделенным ему серверным процессом. На этом этапе listener заканчивает свою работу и ожидает других запросов на подключение. Таким образом если listener не запущен – то вы не сможете установить подключение, однако существующие подключения могут продолжать работу.

Создание listener-а

Listener определяется в файле listener.ora который по умолчанию находится в папке ORACLE_HOME/network/admin. Как минимум файл listener.ora должен содержать информацию об одном listener-e, включая имя listener-а, протокол и адресс. Вы можете настроить несколько listener-ов в одном файле, однако все они должны иметь уникальное имя и адресс.

Как идругие файлы для настройки Oracle Net, файл listener.ora очень привередливый к синтаксису. Важны регистр букв, количество пробелов и аббревиатуры. Поэтому многие DBA не любят редактировать файл самостоятельно (несмотря на то что ничего не мешает это делать вручную). Oracle предоставляет три программы для управления Oracle Net: это Enterprise Manager, Net Manager и Net Configuration Assistant. Оба последних написаны на Java. Функционал этих программ сильно пересекается, однако есть некоторые вещи, которые можно сделать в одной программе, но нельзя в другой и наоборот.

Ниже представлен пример файла listener.ora
LISTENER =

(ADDRESS = (PROTOCOL = TCP)(HOST = jwlnx1)(PORT = 1521))

(ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1522))

(ADDRESS = (PROTOCOL = TCP)(HOST = jwlnx1.bplc.co.za)(PORT = 1522))

В первой секции описан listener с именем LISTENER, который использует локальное имя хоста на порту по умолчанию, 1521. Во второй секции определён второй listener с именем LIST2. Он мониторит порт 1522 также на локальном имене хоста и адресе замыкания (loopback/127.0.0.1).

Для создания listener-а всё что нужно сделать это добавить запись в файл listener.ora и запустить его выполнив команду lsnrctl. В ОС Windows listener будет работать как сервис, но нет нужды создавать его вручную. Он будет создан при первом запуске listener-а. Затем вы можете запускать и останавливать его как обычный сервис windows.

На рисунке 4-4 показана настройка listener-а LIST2 используя Net Manager, а на рисунке 4-5 тот же listener в окне Net Configuration Assistant.

В Net Manager вы можете настроить несколько адресов для мониторинга, а в Net Configuration Assistant нет: он работает только с локальным именем хоста.

Регистрация БД

Listener должен создать серверный процесс для экземпляра БД. Для этого listener должен знать какие экземпляры доступны на компьютере где он запущен. Listener находит информацию об экземплярах в процессе «регистрации». Используя single-instance архитектуру – listener и экземпляр должны быть запущены на одной машине. RAC пользоляет любому listener-у подключаться к любому instanсe в кластере.

Существует два метода регистрации экземпляров БД: статическая и динамическая регистрация. Для статической регистрации вы пишете список эезмепляров в файле listener.ora. Динамическая регистрация обозначает что экземпляр во время запуска, находит listener и регистрируется сам.

Статическая регистрация

Использование динамической регистрации предпочтительно, однако может возникнуть ситуация когда вам придёстя использовать статическую. Динамическая регистрация появилась с версии 8i, и если вам надо настроить listener для подключения к таким БД, то вам придётся регистрировать их статически. Также некоторые приложения требуют статическую регистрацию, в основном приложения для управления. Для статической регистрации экземпляра необходимо создать соответствующую запись в файле listener.ora.

В данном примере запись SID_LIST_LIST2 позволит listener-у с именем LIST2 принимать запросы на подключения к экземпляру с именем ocp11g. Это не значит что instance работает или даже существует. Значение ORACLE_HOME необходима только если listener запускается из домашней директории Oracle отличной от экземпляра. Этот путь используется для поиска исполняемого файла который выполняется для запуска серверного процесса. Обычно это используется при настройке listener-а дял разных версий Oracle, установленных в разные домашние директории.

Динамическая регистрация

Этот метод регистрации является предпочтительным, когда экземпляр регистрирует себя у listener-а. Инилизационный параметр local_listener указывает экземпляру на сетевой адресс который необходимо использовать для поиска и регистрации у listener-а. Во время запуска экземпляра, процесс PMON использует данный параметр для поиска listener-а и информирует его о имени экземпляра и сервисе(ах) которые запускает экземпляр. Имя экземпляра определено в параметре instance_name, а параметр service_names при остутствии значения составляется из параметров instance_name и db_domain (db_domain по умолчанию пустое значение). Возможно создавать и запускать дополнительные сервисы в любое время как изменяя значение параметра service_name (перечисляя через запятую) либо используя пакет DBMS_SERVICE.

Любые изменения должны быть зарегистрированы. Если этого не сделать то listener не будет знать что доступен новый сервис, и не сможет установить соединение. Процесс PMON регистрирует изменения автоматически один раз в минуты, но вы в любое время можете запустить процесс регистрации выполнив команду ALTER SYSTEM REGISTER;

Динамическая регистрации предпочтительнее, так как она позволяет быть увереным что только запущенные экземпляры и доступные сервис зарегистрированы у listener-а и нет ошибок в именах. Очень легко допустить ошибку если вы к примеру редактируете файл listener.ora вручную. Также когда экземпляр останавливается, он автоматически отменить регистрацию.

Начиная с версии 9i динамическая регистрация может не требовать конфигурации совсем, если ваш listener работает используя порт по умолчанию (1521). Все экезмпляры автоматически пытаются найти listener на локальной машине используя порт по умолчанию и в случае успеха – зарегистрироваться у этого listener-а. Если listener не доступен на локальной машине используя порт по умолчанию, вы должны установить где находится listener и перерегистрироваться. Например:

alster system set local_listener=list2;

alter system register;

В данном примере listener указывается используя имя. Это имя необходимо преобразовать в адресс и порт. Однако можно использовать сразу настройки в значении параметра. Например

alter system set local_listener='(address=(protocol=tcp)(host=127.0.0.1)(port=1522))’;

Использование такого значения допускается, однако лучше всё-таки использовать имя, которое настраивается в файле: так как появляется уровень абстракции между именем и физическим адресом. Если адресс listener-а изменится, вы должны сделать изменения в одном месте, а не менять параметры в каждом экземпляре использующим этот listener.

Методы определения имени

Вначале главы мы использовали строку подключения для установления сессии. Эта строка преобразуется в адресс машины где запущен listener и имя экземпляра или сервиса. При динамической регистрации логическое имя listener-а тоже преобразуется в сетевой адресс для регистрации. Доступно четыре метода для преобразования имени: easy connect, local naming, directory naming и external naming. Большинство установок использует local naming, но для сложной и большой системы предпочтительно использовать directory naming.

Easy connect

Метод easy connect был представлен в версии 10g. Его очень использовать – он не требует настройки. Но доступен при использовании только одного протокола: TCP. Остальные методы могут работать с любыми поддеживаемыми протоколами. Easy connect не может использовать дополнительные возможности Oracle Net, такие как балансировка нагрузки или поддержка сетевой маршрутизации. Этот метод часто используется DBA но для пользователей он не сильно удобен. Пример подключения

В этом примере пользовательский процесс использя TCP протокол подключится к порту 1522 по IP адрессу определённому из имени хоста. Если listener запущен на этом порту этого сервера – пользовательский процесс запроси listener создать серверный процесс на instance ocp11g. Можно ещё упростить эту команду

connect store/admin123@ jwlnxl.bplc.co

Такая команда сработает только если listener запущен на порту 1521 и имя сервиса совпадает с именем хоста jwlnxl.bplc.co

Local Naming

Используя эту технику пользователь использует псевдоним (Oracle Net service alias) в строке подключения, а псевдоним преобразуется в сетевой адресс, протокол, сервис или имя экземпляра с помощью локального файла. Этот файл и есть пресловутый tnsnames.ora, который доставил много горя DBA. Рассмотрим пример файла tnsnames.ora

(ADDRESS = (PROTOCOL = TCP)(HOST = jwlnx1.bplc.co.za)(PORT = 1522))

(ADDRESS = (PROTOCOL = TCP)(HOST = serv2.bplc.co.za)(PORT = 1521))

Этот файл содержит два Oracle Net Service alias: ocp11g и test. Эти псевдоним и есть то, что будут использовать пользователи в строке подключения. Первый псевдоним ocp11g указывает на то, что если в строке подключения найдено «@ocp11g», то пользовательский процесс по протоколу TCP, порту 1522 подключится к машине jwlnx1.bplc.co.za и попросит listener создать сессию для экземпляра с названием сервиса ocp11g. Второй алиас test направит пользовательские процессы по другому адресу, порту и сессии будут создаваться для экземпляра testdb.

Метод local naming поддерживает все протоколы и возможность Oracle Net, но управление файлами tnsnames.ora на клиентских машинах может быть задачей, занимающей очень много времени. Также tnsnames.ora файл очень чувствителен к ошибкам синтаксиса. Использование графических программ поможет избегать этих ошибок.

Directory Naming и External Naming

Метод Directory Naming направляет пользовательскую сессию к серверу LDAP для определения псевдонима. LDAP – это широко распространённый стандарт, которого придерживается Oracle и другие производители ПО. Для использования directory naming метода, вначале вам нужно установить и настроить LDAP сервер на каком либо сервере в вашей сети. Oracle предоставляет LDAP сервер ( Oracle Internet Directory) как часть Oracle Application Server, но необязательно использовать именно его. Если у вас уже есть установленный и настроенный к примеру сервер с Microsoft Active Directory – вы можете использовать его.

Как и local naming, метод directory naming поддерживает все возможности Oracle Net – но вместо поддержки файлов tnsnames.ora разбросанных по всей сети, используется централизованное хранилище, что несомненно гораздо легче сопровождать.

External Naming отличается от directory naming только тем, что использует отдельный сервис вместо LDAP – Sun Network Information Services (NIS+) или Cell Directory Services (CDS).

Программа управления listener-ом

Можно запускать и останавливать listener через Database Control, но существует так же консольная программа lsnrctl (или lsnrctl.exe в Windows). Утилита lsnrctl может запускаться через командную строку ОС или через простой графический интерфейс. Для всех команд вы должны указать имя listener-а, если не используется имя по умолчанию LISTENER. На рисунках 4-6 и 4-7 показано как проверить статус listener-а, запустить и остановить его путём вызова команд из командной строки операционной системы или с помощью графического интерфейса.

Необходимо отметить что комнда status всегда отображает адрес по которому listener принимает запросы на подключение, а также имя и местонахождение файла listener.ora, в котором прописан listener и имя и местонахождение файлов логов listenera. На рисунках ниже также видно что listener LIST2 “supports no services”. Это отображается так как не было статически зарегистрировано сервисов и ни один экземпляр БД ещё не зарегистрировался динамически для этого listener-а. На рисунке 4-8 отображено состояние listener-а после динамической регистрации экземпляра БД.

На рисунке 4-8 результат выполнения команды status показывает нам, что listener с именем LISTENER поддерживает три сервиса, доступных для экземпляра БД orc11g:

  • Сервис orcl11g.jwlnx1.bplc.co.za это обычный сервис БД. Listener может запустить выделенную серверную сессию для работы (ещё ни одной сессии не создано)
  • Сервис orcl11gXDB.jwlnx1.bplc.co.za – это сервис для работы с БД основанный на XML. Данный сервис позволяет подключаться к БД используя протоколы отличные от Oracle Net, к примеру FTP и HTTP
  • Сервис orcl11g_XPT.jwlnx1.bplc.co.za – это сервис для работы Dataguard.

По умолчанию экземпляры БД версии 11g регистрируют сервисы XDP и XDT, но они не могут использоваться без дополнительной настройки. Эти сервисы отображаются как “status ready” и это обозначает что они были автоматически зарегистрированы процессом PMON: listener знает что они доступны так как PMON при динамической регистрации указал это. Если бы сервисы были зарегистрированы статически, они бы отображались со статусом “status unknown”. Т.е. сервисы прописаны в файле listener.ora, но могут быть не запущены.

Для просмотра всех доступных команд программы lsnrctl используйте команду HELP

Назначение команд описано ниже

  • START запуск listener-а
  • STOP остановка listener-а
  • STATUS просмотр состояния listener-а
  • SERVICES отобразить сервисы доступны listener-у (более детальная информация чем в команде STATUS)
  • VERSION отобразить версию listener-а
  • RELOAD перечитать файл ora
  • SAVE_CONFIG сохранить изменения в файл listener.ora
  • TRACE разрешить трассировку деятельности listener-а
  • CHANGE_PASSWORD установить пароль для администрирования listener-а
  • QUIT выйти из программы без сохранения
  • EXIT выйти из программы сохранив изменения
  • SET установить значения параметров, таки как примеру время ожидания ответа
  • SHOW отобразить значения установленных параметров

Настройка псевдонимов сервисов (alias)

Выбрав метод определения имени, следующей задачей становится настройка клиентских программ для использования этого метода. Вы можете использовать Database Control, но так как это серверный процесс – вы сможете настроить только программы, которые будут запускаться на том же сервере что и БД. Для настройки можно использовать Net Manager. Это отдельное приложение написанное на языке Java, поставляемое Oracle со всеми клиентскими программами.

Для запуска приложения в среде Unix запустите команду netmgr. В Windows вы можете найти эту программу в меню Пуск.

В дереве навигации доступны три ветки. Ветка Profile используется для установки параметров, которые могут применяться и на серверной и на клиентской стороне Oracle Net и которые могут влиять на поведение все сессий. Ветка Service naming используется для настройки определения имени на клиентской стороне, и ветка Listeners используется для настройки listener-ов БД.

Когда вы выбираете ветку Profile как показано на рисунке 4-9, фактически вы работаете с файлов sqlnet.ora. Этот файл создаётся по умолчанию в папке ORACLE_HOME/network/admin. Он не обязателен, так как для всех параметров доступны значения по умолчанию, но обычно вы будете использовать эту ветку для указания метода определения имени.

Выбрав ветку Profile, вы увидите доступные методы определения имени и три (TNSNAMES, EZCONNECT и HOSTNAME) выбраны по умолчанию: это и есть local naming, easy connect и host naming. External naming указаны как CDS и NIS. LDAP – это directory naming. Host naming это эквивалент Easy Connect и он существует только для обратной совместимости.

Затем вы должны настроить псевдонимы сервисов Oracle Net. Это можно сделать в ветке Service Naming, что фактически создает или изменяет файл tnsnames.ora (по умолчанию местонахождения файла ORACLE_HOME/network/admin). Если у вас настроен метод Directory Naming тогда вам не нужно редактировать ветку Service Naming – достаточно выбрать LDAP в ветке Profile. Пример записи в файле tnsnames.ora показан ниже

(ADDRESS = (PROTOCOL = TCP)(HOST = jwacer.bplc.co.za)(PORT = 1521)

Если пользователь использует “ocp11g” в строке подключения то эта запись используется для отсылки запроса к listener-у по адресу jwacer.bplc.co.za на порт 1521 для создания сессии к экземпляру доступному через сервис ocp11g. Для подключения с помощью этого псведонима достаточно выполнить команду

Используя Easy Connect команда выглядела бы

sqlplus system/manager@ jwacer.bplc.co.za:1521/ocp11g

Для проверки строки подключения можно использовать команду TNSPING. Эта программа принимает строку подключения как параметр, находит файлы Oracle Net, преобразует строку подключения и отправляет запрос к listener-у. Если listener запущен и запрашиваемый сервис зарегистрирован – программа отобразит упешный результат теста. Ниже показан пример работы программы TNSPING

Обратите внимание что результатом команды является имя использованного файла sqlnet.ora, имя метода определения имени и сведения о адресе и порте используемого для теста. Этот инструмент проверяет только listener, т.е. экземпляр может и не быть запущенным.

Имена файлов и системная переменная TNSADMIN

Используется три важных файла для настройки Oracle Net:

  • listener.ora файл на стороне сервера, определяющий listener-ы БД. Влючает в себя сведения о протоколе, адресах и портах, используемых listener-ом для ожидания запросов на подключения. А также может содержать информацию о статических зарегистрированных экземплярах БД.
  • tnsnames.ora – файл со стороны клиента используемый для определения имени. Используется пользовательским процессом для нахождения listener-ов БД.Также может быть использован самим экземпляром БД для нахождения listener-ов для динамической регистрации.
  • sqlnet.ora – файл необязательный, может существовать (и даже с разными значениями) как на клиентской, так и на серверной стороне. Содержит настройки которые могут применяться ко всем сессиям к listener-ам, такие как настройки безопасности и шифрования.

Все три файла по умолчанию находятся в папке ORACLE_HOME/network/admin. Можно изменить путь к ним с помощью системной переменной: TNS_ADMIN. Эта переменная часто используется если сущуствует несколько домашних директорий Oracle. У обычного сервера Oracle будет как минимум три домашних директории Oracle: одна для Enterprise Manager Grid Control Agent, одна для запуска экземпляров и одна для запуска экземпляров ASM (Automatic Storage Management). На клиентских машинах также может быть несколько домашних директорий Oracle, например для клиентов Oracle 10g и Oracle 11g. Установка переменной TNS_ADMIN как указатель на папку одной из домашних директорий (или вообще внешнюю папку) означает, что вам, вместо того чтобы настраивать файлы в двух разных папках, можно будет настраивать файлы в одной папке. Чтобы установить эту переменную в Windows для какой-либо сессии вы можете выполнить команду

Но лучше устанавливать значение этой переменной в регистре.

В Unix и Linux синтаксис может отличаться в зависимости от исползуемой оболочки, но обычно выглядит примерно так

set TNS_ADMIN=/u01/oracle/net; export TNS_ADMIN

Эту команду можно добавить в файл профила каждого пользователя, или в /etc/profile для всех пользователей.

На рисунке 4-10 показан процесс обработки пользовательского запроса. Пользователь инициирует создание подключения к серверу указывая имя пользователя, пароль и строку подключения. Если строка подключения отсутствует, клиент Oracle Net пробует использовать системную переменную ORACLE_SID как значение для строки подключения по умолчанию. Если это значение не установлено – обычно происходит ошибка. Если строка подключения указала, клиент Oracle Net пробует выяснить какой метод использовать дря преобразования строки подключения и для этого необходим файл sqlnet.ora, который может находиться в папке определённой в TNS_ADMIN переменной или ORACLE_HOME/network/admin. Если не установлены ни TNS_ADMIN ни ORACLE_HOME – возвращается ошибка.

Обычно в файле sqlnet.ora находится параметр NAMES.DIRECTORY_PATH, в которой перечислены в порядке предпочтения различные методы определения имени, такие как TNSNAMES, LDAP и EZCONNECT. Если TNSNAMES в списке указан первым, Oracle Net пробует найти файл tnsnames.ora опять же либо в директории указанной в переменной TNS_ADMIN либо в ORACLE_HOME/network/admin. Если файл найден, он используется для преобразования строки подключения в сетевой адрес обычно вида имя хоста:порт:sid или хоста:порт:имя сервиса.

Наконец клиент Oracle Net готов к установке соединения для пользовательского процесса который ициниировал запрос на подключение к БД. Если в строке подключения присутствует символ “@”, тогда происходит запрос к listener-у указанному в сетевом адресе для проверки доступа к экземпляру или сервису. Если listener работа – пользовательский процесс пробует установить соединение с сервером иначе повзращается ошибка. Если в строке подключения нет символа “@” — тогда происходит попытка создать локальное подключение используя протокол IPC и если экземпляр или сервис запущены на той же машине, что и клиентский пользовательский процесс соединение может быть успешно установлено.

Ссылки базы данных

Oracle Net используется для взаимодействия между пользователями и базой данных. Также Oracle Net может использоваться для взаимодействия БД между собой: пользовательская сессия подключенная к одной базе данных может выполнять SQL запросы к другой БД. Это осуществляется с помощью ссылок БД. Существует несколько вариантов для создания ссылок (все связаны с безопасностью), и простым примером является команда

create database link prodstore connect to store identified by admin123 using ‘prod’;

Эта команда создаёт ссылку из текущей БД к удалённой базе данных определяему строкой подключения PROD. Ссылка доступна и может быть использована только для схемы текущего пользователя. Когда будет выполнена команда

select * from orders@prodstore;

Пользовательская сессия попробует создать сессию к удалённой БД, используя имя пользователя STORE и выполнить запрос на удалённом сервере. Результат затем будет возвращён к текущей БД и затем пользователю.

Любые SQL запросы могут быть выполнены используя ссылки БД, если конечно есть соответствующие привилегии доступа. Например рассмотрим такой сценарий:

У вас есть рабочая БД определённая строкой подключения PROD, в которой находится схема STORE содержащая две таблицы: ORDERS и PRODUCTS. Создана ссылка к этой БД (командой описанной выше). Также есть база данных для разработки, определённая строкой подключения DEV, в которой также есть схема STORE. Вы подключены к третьей базе данных с именем TEST и вам нужно обновить схему базы данных для разработки данными из рабочей БД.

Для начала создадим ссылку на базу данных для разработки

create database link devstore connect to store identified by devpasswd using ‘dev’;

Затем обновим данные в БД для разработки используя рабочую базу

truncate table orders@devstore;

truncate table products@devstore;

insert into orders@devstore select * from orders@prodstore;

insert into products@devstore select * from products@prodstore;

В будущем если вам необходимо проверить были ли добавлены данные в рабочую базу данных и если были, то добавить эти данные в БЛ для разработки вы можете выполнить команду

insert into orders@devstore (select * from orders@prodstore minus select * from orders@devstore)

Если к примеру необходимо обновить имя покупателя вы можете сделать это в двух базах данных одновременно

update customers@prodstore set customer_name=’Coda’ where customer_ >

update customers@devstore set customer_name=’Coda’ where customer_ >

Когда необходимо Oracle выполнит дву-фазное подтверждение транзакции, чтобы убедиться что распределённая транзакция (distributed transaction – это транзакция затрагивающая данные в нескольких базах данных) обрабатывается как атомарная транзакция: изменения должны применяться либо ко всем базам данных либо ни к одной. Согласованность чтения данных также управляется во всём окружении.

Илон Маск рекомендует:  Что такое код ldexp экспонента
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL