Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > Запрос с параметрами


Автор: MasterOfCode 7.4.2010, 13:11
Добрый день всем.
Хочу увидеть результат в виде таблицы. Делаю так:

Код

DECLARE
start_period date;
end_period date;
begin
start_period := '01.03.2010';
end_period := '01.04.2010';
select *  
from table1 t1
where t1.registerdate between start_period and end_period; 
end;


Ругается, просит into вставить, а мне незачем однострочный ответ. Вопрос, как делать правильно?

Автор: azesmcar 7.4.2010, 13:13
создай процедуру и возвращай в курсор.

Автор: MasterOfCode 7.4.2010, 13:15
Цитата(azesmcar @  7.4.2010,  15:13 Найти цитируемый пост)
создай процедуру и возвращай в курсор. 

И что, приходится всегда так извращаться с курсорами? В MS SQL  с этим намного проще.

Автор: azesmcar 7.4.2010, 13:16
Цитата(MasterOfCode @  7.4.2010,  13:15 Найти цитируемый пост)
И что, приходится всегда так извращаться с курсорами?

Почему извращаться? Это так и делается.

Автор: MasterOfCode 7.4.2010, 13:18
Цитата(azesmcar @  7.4.2010,  15:16 Найти цитируемый пост)
почему извращаться? 

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

Автор: azesmcar 7.4.2010, 13:21
я просто не понимаю чего тут сложного, написание open cursor как-то усложняет работу? По мне так нормально.

Автор: MasterOfCode 7.4.2010, 13:39
Цитата(azesmcar @  7.4.2010,  15:21 Найти цитируемый пост)
я просто не понимаю чего тут сложного, написание open cursor как-то усложняет работу? По мне так нормально.

К примеру как это выглядит в MS SQL
Код

DECLARE @start_period date;
DECLARE  @end_period date ;
SET @start_period = '2010-03-01';
SET @end_period = '2010-04-01';
select * from table1 where t.registerdate between @start_period and @end_period; 


А в оракл нужно еще какие sys_refcursor использовать.

Автор: azesmcar 7.4.2010, 13:46
Код

create or replace procedure(data out sys_refcursor)
declare
   start_period date := to_date('2010-03-01');
   end_period date := to_date('2010-03-01');
begin
   open data for select * from table1 where t.registerdate between @start_period and @end_period;
end;

ну и что тут сложного?

код может быть не рабочим, писал тут и на память, нет оракла под рукой.

Автор: DimW 7.4.2010, 15:28
MasterOfCode, для того что бы написать запрос с параметрами не требуется писать процедурный код:
Код

select *
  from table1
 where t.registerdate between :start_period and :end_period


обратите внимание на двоеточие.
соответственно передавать значения в эти параметры будете средствами вашего инструмента или библиотек котрые используете для работы с оракл.

Автор: azesmcar 7.4.2010, 15:39
DimW

Да конечно, но я думаю запросы в любом случае лучше писать в процедурах и возвращать через курсор так как

1. В случае вызова запроса извне он становится динамическим, а значит тратится дополнительное время на компиляцию.
2. Так нагляднее выглядит - передал аргументы и получил результат.
3. Код становится чище и аккуратнее, если в нем вместо огромных запросов стоит вызов процедуры.
4. Код легче отлаживать и проверять, запустил процедуру в PL/SQL, проверил результат и не надо запускать саму программу и делать dump запроса, чтобы посмотреть что там получилось.

Я так думаю © smile

Автор: DimW 7.4.2010, 16:27
Цитата(azesmcar @  7.4.2010,  15:39 Найти цитируемый пост)
1. В случае вызова запроса извне он становится динамическим, а значит тратится дополнительное время на компиляцию.

утверждение не верно.

полный разбор:
- синтаксический разбор;
- морфологический разбор;
- определение наиболее оптимального плана выполнения запроса; (самая дорогая операция при разборе запроса)

частичный разбор:
- синтаксический разбор;
- морфологический разбор;

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

если ты действительно значения в запрос добавляешь динамически(не используя переменные привязки), то оракл всегда будет выполнять полный разбор.


Цитата(azesmcar @  7.4.2010,  15:39 Найти цитируемый пост)
2. Так нагляднее выглядит - передал аргументы и получил результат.
3. Код становится чище и аккуратнее, если в нем вместо огромных запросов стоит вызов процедуры.
4. Код легче отлаживать и проверять, запустил процедуру в PL/SQL, проверил результат и не надо запускать саму программу и делать dump запроса, чтобы посмотреть что там получилось.

спорить не буду дело вкуса smile
просто новечку в оракл лучше знать о простом способе.

Добавлено @ 16:32
к стати при таком варианте:
Код

create or replace procedure(data out sys_refcursor)
declare
   start_period date := to_date('2010-03-01');
   end_period date := to_date('2010-03-01');
begin
   open data for select * from table1 where t.registerdate between start_period and end_period;
end;


в действительности запрос керируемый ораклом будет выглядеть примерно так:
Код

select * from table1 
where t.registerdate between :1 and :2;


делается это для того что бы избежать ситуаци когда используя этот же запрос, программист использует другие переменные (к примеру start_date, end_date), тем самым избежать полного разбора.

Автор: azesmcar 7.4.2010, 16:33
Цитата(DimW @  7.4.2010,  16:27 Найти цитируемый пост)
если морфология идентична при повторном выполнении запроса, то подбор плана сервер не делает т.к. он уже для него есть.

Не знал что он кеширует..раньше вроде не делал.

Цитата(DimW @  7.4.2010,  16:27 Найти цитируемый пост)
просто новечку в оракл лучше знать о простом способе.

 smile 

Автор: DimW 7.4.2010, 16:38
Цитата(azesmcar @  7.4.2010,  16:33 Найти цитируемый пост)

Не знал что он кеширует..раньше вроде не делал.


я оракл начал изучать с 8 версии, там уже все было в порядке.
если интересно можете посмотреть вьюху v$sql.

Автор: azesmcar 7.4.2010, 16:40
Цитата(DimW @  7.4.2010,  16:38 Найти цитируемый пост)
я оракл начал изучать с 8 версии, там уже все было в порядке.

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

Автор: DimW 7.4.2010, 16:50
Цитата(azesmcar @  7.4.2010,  16:40 Найти цитируемый пост)
8 лет назад было

да, давненько.
сам уже почти год не шерстил концепт по новым версиям, по этому сейчас на 11G R2 пишу так же как и под 9i, в принципе необламываюсь, но понимаю что не хорошо это  smile 

Автор: azesmcar 7.4.2010, 16:54
Да, это я тогда только на работу поступил и сразу Oracle -ом по башке smile 
Так что это было мое первое знакомство с базами данных, 2 года там проработал и после этого как-то сменил профиль, серьезно базами уже не занимаюсь, вот никак не нахожу повода прочитать чего нибудь современного и серьезного.

Автор: Zloxa 8.4.2010, 09:14
Цитата(MasterOfCode @  7.4.2010,  13:39 Найти цитируемый пост)
К примеру как это выглядит в MS SQL

не правда ли мутный пример? Он ничего не показывает. 
Откуда Вы вызваете эот скрипт? С клиента? Почему бы здесь сразу не использовать связанные пременные(параметры)?
Или же это sql скрипт, который выполняется неким шеллом? Для оракла штатным шеллом является sqlplus, а он поддерживает и макросы и и переменные:
Код
SQL> var val number
SQL> define foo=dual
SQL> exec :val := 10;

PL/SQL procedure successfully completed.

SQL> select :val from &foo;
old   1: select :val from &foo
new   1: select :val from dual

      :VAL
----------
        10

SQL> 
 

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

Автор: Zloxa 8.4.2010, 09:51
Цитата(azesmcar @  7.4.2010,  15:39 Найти цитируемый пост)
писать в процедурах и возвращать через курсор

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

Автор: MasterOfCode 8.4.2010, 10:35
Цитата(Zloxa @  8.4.2010,  11:14 Найти цитируемый пост)
Мне думается что следует понимать, что для Оракла не работает абсолютное большинство бест практис MS SQL, ровно как и наоборот. Может расскажете что конкретно Вы пытаетесь сделать,  вместо того, чтобы рассказывать как вы всегда это делали в MS SQL и показывать бессмысленные примеры, а мы постараемся Вам рассказать как это делается в Оракле? 

я пытался сделать так, как я привык. просто набор запросов. нажав на "execute", в PL/SQL Developer чтоб начались выполнятся поочередно скрипты и в результате получить таблицу. вот и все, собственно. Поскольку у меня в нескольких запросах, используются одинаковые периоды времени, необходимо один раз подправить вначале и везде автоматом сменится.
пример:

Код

/*Блок где объявляются и присваиваются переменные :s_period и :e_period*/
create table temp_table_1
as
select * from table_1 t where t.date between :s_period and :e_period;

create table temp_table_2
as
select * from table_2 t where t.date between :s_period and :e_period;

select * 
from temp_table_1 t1
        left join temp_table_2 t2 on t1.id = t2.id


Писал от руки, возможно где то ошибся.

Автор: Zloxa 8.4.2010, 11:31
Цитата(MasterOfCode @  8.4.2010,  10:35 Найти цитируемый пост)
 в PL/SQL Developer

Command window PL/SQL девелопера эмулирует некоторые команды sqlplus'а
Код

SQL> var from_date date
SQL> var to_date date
SQL> exec :from_date := sysdate -1; :to_date := sysdate +1;
 
PL/SQL procedure successfully completed
from_date
---------
07.04.2010 12:28:15
to_date
---------
09.04.2010 12:28:15
SQL> select * from dual where sysdate between :from_date and :to_date;
 
DUMMY
-----
X
from_date
---------
07.04.2010 12:28:15
to_date
---------
09.04.2010 12:28:15
 
SQL> 


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)