Перейти к содержимому

Фотография

Работать с БД


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 36

#21 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 11 июля 2008 - 09:51

На строчке "Result := RecSet.GetString" получаю такое ругательство: ADODB.Recordset Операция не допускается, если объект закрыт.


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

//JScript
var AConnection,  RecSet;
AConnection = ADO.CreateADOConnection();
AConnection.ConnectionString = "Provider=SQLOLEDB.1; Persist Security Info=False; User ID = ...; Password = ...; Database = ...; Data Source = ...";
AConnection.LoginPrompt = false;
AConnection.Open(); 
RecSet = AConnection.Execute_(sqltext); 
RecSet.MoveFirst();  
while(!RecSet.EOF)
{
	Log.Message(RecSet.Fields(column_index).Value)
	RecSet.MoveNext();
}
AConnection.Close();


Попробовала .. - тот же эффект. Причем процедура в пакете выполняется, а функция не хочет... если она не в пакете работает...
  • 0

#22 AlexP

AlexP

    Опытный участник

  • Members
  • PipPipPipPip
  • 406 сообщений
  • Город:Санкт-Петербург

Отправлено 11 июля 2008 - 12:06

...Попробовала .. - тот же эффект. Причем процедура в пакете выполняется, а функция не хочет... если она не в пакете работает...


Правильно ли я Вас понял:
1) если код поместить в функцию и эту функцию выполнить - ошибок не будет
2) если код поместить в функцию и эту функцию вызвать из другой - получаем ошибку
?

...получаю такое ругательство: ADODB.Recordset Операция не допускается, если объект закрыт.


Запостите оригинальный текст ошибки.
  • 0

#23 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 11 июля 2008 - 12:10

Попробовала .. - тот же эффект. Причем процедура в пакете выполняется, а функция не хочет... если она не в пакете работает...


Правильно ли я Вас понял:
1) если код поместить в функцию и эту функцию выполнить - ошибок не будет
2) если код поместить в функцию и эту функцию вызвать из другой - получаем ошибку
?


Нет, не правильно.
Если в БД функция "create or replace function...." создана просто так (не в пакете), то все работает.
Но если эту функцию в БД поместить в пакет "create or replace package body...", то из комплита она не вызывается....
  • 0

#24 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 11 июля 2008 - 12:12

Попробовала .. - тот же эффект. Причем процедура в пакете выполняется, а функция не хочет... если она не в пакете работает...


Правильно ли я Вас понял:
1) если код поместить в функцию и эту функцию выполнить - ошибок не будет
2) если код поместить в функцию и эту функцию вызвать из другой - получаем ошибку
?


Нет, не правильно.
Если в БД функция "create or replace function...." создана просто так (не в пакете), то все работает.
Но если эту функцию в БД поместить в пакет "create or replace package body...", то из комплита она не вызывается....


В спецификации пакета функция объявлена - с точки зрения БД все корректно.(ну или я чего-то не знаю)
  • 0

#25 AlexP

AlexP

    Опытный участник

  • Members
  • PipPipPipPip
  • 406 сообщений
  • Город:Санкт-Петербург

Отправлено 11 июля 2008 - 12:28

Нет, не правильно.
Если в БД функция "create or replace function...." создана просто так (не в пакете), то все работает.
Но если эту функцию в БД поместить в пакет "create or replace package body...", то из комплита она не вызывается....


Всё, вспомнил: получал точно такую же ошибку при вызове процедуры. Обошёл следующим образом: создавал временную таблицу и заполнял её процедурой, а в TestComplete'е работал уже с таблицей. Не знаю, на сколько подобный подход будет приемлем в вашем случае...
  • 0

#26 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 11 июля 2008 - 12:43

Нет, не правильно.
Если в БД функция "create or replace function...." создана просто так (не в пакете), то все работает.
Но если эту функцию в БД поместить в пакет "create or replace package body...", то из комплита она не вызывается....


Всё, вспомнил: получал точно такую же ошибку при вызове процедуры. Обошёл следующим образом: создавал временную таблицу и заполнял её процедурой, а в TestComplete'е работал уже с таблицей. Не знаю, на сколько подобный подход будет приемлем в вашем случае...



Не совсем поняла...что такое временная таблица? - Таблица в БД или массив в ТС?
Если это таблица в БД, то:
1. Как она может быть временной?
2. Означает ли "заполнял её процедурой" - что таблица состоит из одного поля, текстом кот. является процедура?
  • 0

#27 AlexP

AlexP

    Опытный участник

  • Members
  • PipPipPipPip
  • 406 сообщений
  • Город:Санкт-Петербург

Отправлено 11 июля 2008 - 12:57

Не совсем поняла...что такое временная таблица? - Таблица в БД или массив в ТС?


Таблица БД.

Если это таблица в БД, то:
1. Как она может быть временной?


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

2. Означает ли "заполнял её процедурой" - что таблица состоит из одного поля, текстом кот. является процедура?


Процедура возвращала records set. Я создавал таблицу и insert'ил в неё данные из процедуры (как то так):

-- T-SQL
SET NOCOUNT ON

create table ##TempTable (
col1 int, 
col2 cahr(128))

insert into ##TempTable
exec [procedure_name]

select * from ##TempTable

Этот скрипт возвращал валидный records set.
  • 0

#28 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 11 июля 2008 - 13:15

Не совсем поняла...что такое временная таблица? - Таблица в БД или массив в ТС?


Таблица БД.

Если это таблица в БД, то:
1. Как она может быть временной?


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

2. Означает ли "заполнял её процедурой" - что таблица состоит из одного поля, текстом кот. является процедура?


Процедура возвращала records set. Я создавал таблицу и insert'ил в неё данные из процедуры (как то так):

-- T-SQL
SET NOCOUNT ON

create table ##TempTable (
col1 int, 
col2 cahr(128))

insert into ##TempTable
exec [procedure_name]

select * from ##TempTable

Этот скрипт возвращал валидный records set.


А, ну в моем случае это смысла не имеет, поскольку мне функция возвращает результат из бд если она не в пакете, просто чтобы все было правильно с точки зрения программирования, считается не красивым использование процедур и функций не в пакете..
Интересен сам факт, почему же у меня так не получается? Может ли быть что TС не поддерживает возможность подобной работы....?
  • 0

#29 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 14 июля 2008 - 04:11

Здравствуйте, Умница.

Я, к сожалению, не знаком с понятием "пакетов", о которых вы говорите. Не могли бы вы вкратце рассказать какая у вас СУБД и как такие "пакеты" создаются?
  • 0
С уважением,
Дмитрий

#30 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 14 июля 2008 - 09:28

Здравствуйте, Умница.

Я, к сожалению, не знаком с понятием "пакетов", о которых вы говорите. Не могли бы вы вкратце рассказать какая у вас СУБД и как такие "пакеты" создаются?


СУБД у нас Oracle 10g

Пакеты: Пакет -> Тело пакета -> процедура и функция(как еще объяснить? код создания пакета написать?)
  • 0

#31 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 15 июля 2008 - 04:56

Здравствуйте.

Спасибо за объяснение. Хотел попробовать и сам посмотреть, но, к сожалению, Oracle под рукой нет и попробовать не могу.

Единственное, что могу посоветовать, это поискать в Интернете по точному тексту ошибки (надеюсь, он на английском). Наверяка кто-нибудь уже сталкивался и нашёл причину проблемы, не думаю что она в TestComplete.
  • 0
С уважением,
Дмитрий

#32 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 15 июля 2008 - 09:14

Еще вопрос по теме:
У меня строка Cmd.Parameters.Refresh; занимает от 5сек - это существенно замедляет работу... нельзя ли как уменьшить время выполнения запроса? И от чего это зависит...?
  • 0

#33 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 15 июля 2008 - 11:11

Здравствуйте.

Согласно этой статье MSDN Library, вызов Refresh заставляет ADO обратиться к базе для получения информации о параметрах команды. Согласно этой же статье, можно избежать вызова этого метода создав паметры вручную, но для этого надо точно знать их тип.
  • 0
С уважением,
Дмитрий

#34 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 15 июля 2008 - 11:37

Здравствуйте.

Согласно этой статье MSDN Library, вызов Refresh заставляет ADO обратиться к базе для получения информации о параметрах команды. Согласно этой же статье, можно избежать вызова этого метода создав паметры вручную, но для этого надо точно знать их тип.


Пытаюсь так сделать.. но на все типы он мне ругается либо "Неверный тип параметра" либо "тип данных SQL выходит за пределы допустимого диапазона"
Prm := Cmd.CreateParameter('aParamName', adChar, adParamInput, 2000);

У меня DelphiScript, TC4
Кто знает какой тип понимает DelphiScript?
  • 0

#35 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 16 июля 2008 - 03:42

Здравствуйте.

Трудно сказать. А показать саму stored procedure, или хотя бы определение параметров можете?
  • 0
С уважением,
Дмитрий

#36 Умница

Умница

    Новый участник

  • Members
  • Pip
  • 29 сообщений

Отправлено 16 июля 2008 - 08:02

Здравствуйте.

Трудно сказать. А показать саму stored procedure, или хотя бы определение параметров можете?


Все могу :-).. Причем, через Parameters.refresh и т.д. работает (если она не в пакете), но.... CreateParameter... не работает даже если не в пакете...

Функция такая:

FUNCTION func1 (aParamName IN tcstandardparam.paramname%TYPE)
RETURN tcstandardparam.paramvalue%TYPE
IS
lParamValue tcstandardparam.paramvalue%TYPE;
BEGIN
SELECT PARAMValue
into lParamValue
FROM tcstandardparam sp
WHERE sp.paramname = UPPER(aParamName);

RETURN lParamValue;

EXCEPTION
WHEN NO_DATA_FOUND
THEN
RAISE_APPLICATION_ERROR(-20008, 'Стандартного парметра с именем ' ||
aParamName || ' в таблице нет!!!' );
END;

Вызывать пыталась следующим образом:

вариант 1

Function F1(aParam: string): OleVariant;
var
RecSet, Prm, Cmd: OleVariant;
begin
Cmd := ADO.CreateCommand;
Cmd.ActiveConnection := ...
Cmd.CommandText := 'declare res varchar2(2000); begin res := Func1(aParam); end;';
Prm := aCmd.CreateParameter('aParam', adVarChar, adParamInput, 2000);
Prm.Value := aParam;
Cmd.Parameters.Append(Prm);
RecSet := Cmd.Execute;
.....
end;

вариант 2

Function F1(aParam: string): OleVariant;
var
RecSet, Prm, Cmd: OleVariant;
begin
Cmd := ADO.CreateCommand;
Cmd.ActiveConnection := ...
Cmd.CommandText := 'declare res varchar2(2000); begin res := Func1(' + '''' + aParam+ '''' + '); end;';
Prm := aCmd.CreateParameter('res', adVarChar, adParamOutPut, 2000);
Cmd.Parameters.Append(Prm);
RecSet := Cmd.Execute;
.....
end;


вариант 3

Function F1(aParam: string): OleVariant;
var
AConnection, RecSet, Prm, Cmd: OleVariant;
begin
AConnection := ADO.CreateADOConnection;
AConnection .ConnectionString := ...
AConnection.LoginPrompt = false;
AConnection.Open();

RecSet = AConnection.Execute_(declare res varchar2(2000); begin res := Func1(' + '''' + aParam+ '''' + '); end;);
.....
end;

Результат один: ADODB.Recordset Операция не допускается, если объект закрыт.
  • 0

#37 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 17 июля 2008 - 04:13

Здравствуйте.

Почитайте эту статью, может найдёте что-нибудь полезное. Также, попробуйте использовать ODBC для доступа к базе (нужный connection string найдёте на www.connectionstrings.com).
  • 0
С уважением,
Дмитрий


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных