Преобразование расширенной хранимой процедуры из T-SQL в PL-SQL

Я хочу преобразовать вручную ниже хранимой процедуры из T-SQL (MS SQL Server 2008) в P-SQL (Oracle DB 11g). Недавно я попытался преобразовать эту процедуру с помощью SQL Developer и SwisSQL Tool, но безуспешно. Эта хранимая процедура содержит один параметр @sptotest для поиска одного слова. Вот код:

T-SQL:

CREATE PROCEDURE sp_name @sptotest sysname AS

DECLARE @d            datetime,
       @tookms       int,
       @cnt          int,
       @single_email varchar(80),
       @word         varchar(50)

DECLARE @testwords TABLE
       (no   int         NOT NULL PRIMARY KEY,
        word varchar(80) NOT NULL)

CREATE TABLE #temp(person_id  int          NOT NULL PRIMARY KEY,
                  first_name nvarchar(50) NULL,
                  last_name  nvarchar(50) NOT NULL,
                  birth_date datetime     NULL,
                  email      varchar(80)  NOT NULL)



SELECT TOP 1 @single_email = email
FROM   persons
WHERE  person_id BETWEEN 321106 AND 325000 AND  email LIKE '%.com'
ORDER  BY person_id


INSERT @testwords(no, word)
  SELECT 1, 'joy'
  UNION ALL
  SELECT 4, @single_email

PRINT '------------------ Testing ' + ' ' + quotename(@sptotest) + ' ----'

DECLARE cur CURSOR STATIC LOCAL FOR
  SELECT word FROM @testwords ORDER BY no
OPEN cur

WHILE 1 = 1
BEGIN
  FETCH cur INTO @word
  IF @@fetch_status <> 0
     BREAK

  TRUNCATE TABLE #temp

  CHECKPOINT
  DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS


  SELECT @d = getdate()
  INSERT #temp
     EXEC @sptotest @word
  SELECT @tookms = datediff(ms, @d, getdate())
  SELECT @cnt = COUNT(*) FROM #temp
  PRINT ltrim(str(@tookms)) + ' ms, ' +
        ltrim(str(@cnt)) + ' rows. Word = "' + @word + '".'


  TRUNCATE TABLE #temp
  SELECT @d = getdate()
  INSERT #temp
     EXEC @sptotest @word
  SELECT @tookms = datediff(ms, @d, getdate())
  SELECT @cnt = COUNT(*) FROM #temp
  PRINT ltrim(str(@tookms)) + ' ms, ' +
        ltrim(str(@cnt)) + ' rows. Word = "' + @word + '". Data in cache.'

END

DEALLOCATE cur

Заранее спасибо.

1
nl ja de
В большинстве случаев вам не нужны все эти обходные пути, использующие временные таблицы в Oracle, поскольку Oracle не блокирует строки при их выборе. Если вы можете использовать только один запрос, который будет намного лучше в Oracle
добавлено автор a_horse_with_no_name, источник
Привет и приветствуем переполнение стека! Во-первых, переводы обычно не по теме, но поскольку вы опубликовали то, что вы пытаетесь перевести на хорошо сделанные, и спасибо! Это делает ваш вопрос намного лучше и более ответственным. Тем не менее, нам также нужно знать , что неправильно с вашим переводом. Почему он не работает? Были ли у вас какие-то ошибки и какие были? Не дает ли тот же результат? Какой результат вы ожидали и какую процедуру пытаетесь сделать?
добавлено автор Ben, источник
Какой у Вас вопрос?
добавлено автор Roy Dictus, источник
Возможно, вы захотите провести несколько слов о том, что должен делать хранимый процесс, и что не так с вашим переводом.
добавлено автор Hans Kesting, источник

1 ответы

You can't create a table inside a procedure directly. You have to use execute immediate to create a global temporary table. You would need to use declare

Объявление курсора должно быть в объявлении, которое означает над выражением begin .

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

Маленький пример для немедленного выполнения #

begin
  execute immediate 'create table t23 as  select ''1'' aa from dual'; 
  execute immediate 'update t23 set aa =''2'' where aa=''1''';
  COMMIT ;
end;

And your Proc Follows

create or replace procedure test_sp 
(
sptotest in varchar2 default null
)
 as
d date;
tookms number;
cnt number;
single_mail varchar2(80);
word varchar2(50);

cursor cur is select word from testwords order by no;

begin
execute immediate ('create global temporary table testwords
(
no     int          not null,
word   varchar2(80) not null,
PRIMARY KEY(no)
)');

execute immediate ('create global temporary table temp
(
person_id   int           not null,
first_name  nvarchar2(50) null,
last_name   nvarchar2(50) not null,
birth_date  date          null,
email       varchar2(80)  not null,
PRIMARY KEY(person_id)
)');

select Colm_name into Variable_name
from persons
where person_id between 311106 and 32500 and email like '%.com'
order by person_id;

insert into testwords
(
no, 
word
)
select 1, 'joy' from Table_name1
union all
select 4, single_email from Table_name2;

DBMS_OUTPUT.PUT_LINE(  '------------------ Testing '  || ' '  || CAST(sptotest AS  VARCHAR2)  || ' ----');  

open cur; 
 -- Cursor Processing
Close Cur;
end test_sp;
/
0
добавлено
@IvanB d't работает как есть, я использовал фиктивные столбцы и таблицы в proc, изменен на ваши таблицы и попытаюсь исправить эти незначительные ошибки.
добавлено автор Dileep, источник
Для вашего вопроса все должно быть связано с курсором. прочитайте о атрибутах курсора, чтобы вы не знали, как использовать. открыть курсор Если cur% notfound, тогда выйдите.
добавлено автор Dileep, источник
Привет a_house_with_no_name, я использовал вашу хранимую процедуру, преобразованную в pl/sql, но когда я запускаю процедуру, есть такие ошибки, как: Ошибка (12,15): PL/SQL: заявление SQL игнорируется
добавлено автор IvanB, источник
Привет @a_house_with_no_name, я использовал вашу хранимую процедуру, преобразованную в pl/sql, но когда я запускаю процедуру, есть такие ошибки, как: Ошибка (12,15): PL/SQL: заявление SQL игнорируется, ошибка (12,32): PL/SQL: ORA-00942: таблица или представление не существует, ошибка (37,1): PL/SQL: заявление SQL игнорируется, ошибка (42,22): PL/SQL: ORA-00942: таблица или представление не существует, ошибка (46,1): PL/SQL: заявление игнорируется. Спасибо заранее.
добавлено автор IvanB, источник
Привет @Dileep, мне очень жаль этот комментарий, потому что я новичок в oracle pl-sql, и я не запускал процедуру правильно, ваша процедура - WORKING. Также вы можете показать мне, как преобразовать приведенные выше строки процедуры: WHILE 1 = 1 BEGIN FETCH IN IN IN IF IF @@ fetch_status <> 0 BREAK TRUNCATE TABLE #temp CHECKPOINT DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS SELECT d = getdate() INSERT # temp EXEC sptotest word SELECT takems = dateiff (ms, d, getdate ()) SELECT cnt = COUNT (*) FROM #temp
добавлено автор IvanB, источник
Привет @Dileep, спасибо за инструкции.
добавлено автор IvanB, источник
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)

Oracle RU
Oracle RU
303 участник(ов)

Русскоязычная группа по Oracle. — Архитектура СУБД — PL/SQL — Оптимизация — Администрирование — Вакансии Oracle (указать инфу по вилке ЗП и удалёнке) Приглашайте коллег :-) Запрещены: личные оскорбления, обсуждения оффтопик вопросов политики и религии