Страница 1 из 1

{prop:sql} и переменные clarion

Добавлено: 25 Январь 2006, 20:21
lsgsoftware
myfile{prop:sql}='insert into myfile set name=''проверка''' - работает
а фигово это, а если в присваиваемом значении будет присутствовать тоже кавычка, запятая... - будет ошибка синтаксиса, тут надо биндить параметры
и запросы должны иметь следующий вид:

Код: Выделить всё

insert into myfile set name = ?
А вот такие конструкции ( где s-string)
myfile{prop:sql}='insert into myfile set namt=&s'
myfile{prop:sql}='insert into myfile set namt=@s'
не работают !!!
и тут надо биндить параметры

Код: Выделить всё

insert into myfile set namt=?
как биндить - если это DRIVER('ODBC') или DRIVER('MSSQL') то через ODBC API, штатно такого нет

Добавлено: 25 Январь 2006, 22:11
Дед Пахом
myfile{prop:sql}='insert into myfile set name=''' & clip(s) &''''
так не работает?

'select 2*2' можно выполнить вроде только как {prop:sql}=, поэтому без файла не обойтись.

А вот как можно

Добавлено: 26 Январь 2006, 11:19
Andrew™
извиняюсь что затёр первое письмо, случайно вместо цитата нажал правка, хотя письмо не моё.

а вот как хотелось и как делается у меня

Код: Выделить всё

tmp  MAVExecute
Str   CSTRING(100)
    CODE
 Str = 'проверка'
 tmp.BindParameter(Str)
 if tmp.run('insert into myfile set nameT=?')
  mavshowerror
 end

Код: Выделить всё

tmp  MAVExecute
ret   LONG
    CODE
 tmp.BindParameter(ret,SQL_PARAM_OUTPUT)
 if tmp.run('? = select 2*2')
  mavshowerror
 end

Добавлено: 26 Январь 2006, 19:07
lsgsoftware
Спасибо Деду Пахому! Вариант
myfile{prop:sql}='insert into myfile set name=''' & clip(s) &''''
работает и без bind
Теперь вот мучаюсь с присвоением кларион-переменной значения из SQL типа этого
t - long
Myfile{Prop:SQL}= 'set t=(select 2*2)'
Пока расстанвка кавычек к успеху не привела
Вообще в доке клары по работе с SQL практически ничего нет(крошечный раздельчик embedded sql, из которого мало что можно понять).Работать с MAV я морально не готов(рановато мне)
Может кто подскажет, что можно почитать по теме, а лучше скинет фрагмент текста реального кода, в котором есть разнообразные варианты работы с {prop:SQL}.
Заранее благодарен

Добавлено: 26 Январь 2006, 22:23
Дед Пахом
Вообще говоря, есть такая технология:
заводим в словаре один файл с одним полем string(1024 например), его же имеем на сервере (можно при старте программы создавать, а при выходе грохать).
Создаём одну процедуру ExecSQL(), которая делает thatfile{prop:sql}=какой-то-там-запрос, и другую Getdata(), которая делает один NEXT(thatfile); если NEXT() вернул ERRORCODE() <> 0, то процедура возвращает false, иначе true. Сама она описана как Getdata(<*?>,<*?>,,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>,<*?>), BYTE,PROC
ВСЕ запросы сервера должны возвращать данные в виде cast(a,varchar)+CHR(13)+cast(b.varchar)+CHR(13)... и т.д., т.е. строки, разделённые спецсимволом. В процедуре парсим строку по этому символу, запихивая каждое значение в соответствующий выходной параметр процедуры
ExecSQL('SELECT 2*2')
GetData(t)

Добавлено: 01 Февраль 2006, 8:13
lsgsoftware
Профессиональное решение - прямая работа с ODBC -наверное самое правильное ( на то Андрей -SQL-профи).Но во-первых это очень муторно, и во-вторых есть мнение, что возникнут проблемы с ODBC-драйвером MYSQL(велосипедисты скорее всего этот драйвер не тестировали).Я тут подумал и изобрел ламерский приемчик.Суть решения
- заводим "фальшивую" таблицу XXX из одной записи, поля которой - переменные, требуемые для обмена Sql-Clarion.
Например d-int !(long)
sss-char(255) ! string(255)
uid -int !(long)
Далее примерно так
set(xxx);next(xxx)
if error()
uid=1
sss='Одуванчик'
add(xxx)
else
sss='Одуванчик'
put(xxx)
.
myfile{prop:sql}='insert into myfile set name=(select sss from xxx);'
!после этого в таблице Myfile появляется запись где имя='одуванчик'
xxx{prop:sql}=' update table xxx set d=(select max(uid) from myfile);'
set(xxx);next(xxx)
и имеем xxx:d - идентификатор последней добавленной записи
Вроде все прозрачно, просто и работает
Коллеги, хотелось бы услышать Ваше мнение

Добавлено: 01 Февраль 2006, 9:48
PV
А я делаю так:
В случае выполнения запроса:
Например, таблица MyFile содержит такие поля в зависимости от типа ожидаемого результата:
ResLong Long,
ResReal decimal(12,5)
ResString cstring(256)

Тогда, чтобы вернуть результат типа LONG:

MyFile{PROP:SQL}='Select 2*2 as ResLong, 0 as ResReal, " " as ResString from Anytable '
Next(MyFile)
if errorcode()
message(Error()&'-'&Fileerror(),'Ошибка')
Else
stop(MyFile:ResLong&' '&MyFile:ResReal&' '&MyFile:ResString)
.

Чтобы вернуть результат типа DECIMAL:

MyFile{PROP:SQL}='Select 0 as ResLong, 45/25 as ResReal, " " as ResString from Anytable '
Next(MyFile)
if errorcode()
message(Error()&'-'&Fileerror(),'Ошибка')
Else
stop(MyFile:ResLong&' '&MyFile:ResReal&' '&MyFile:ResString)
.

Аналогично и в случае CSTRING
Как видно из примера, возвращаются все три параметра сразу. Вам только решать какой результат вы ждете

В случае возврата параметра из хранимой процедуры:

bind('pack',newpachka)

share(FUNCTIONFORSQL)

FUNCTIONFORSQL{prop:sql}='NORESULTCALL correct_package.FindFreePackageNum(&pack[OUT])'

Cheks:PackageNum = newpachka

close(FUNCTIONFORSQL)

Как видите, перед именем BIND-переменной достаточно поставить "&" и указать, что параметр возращается, используя "[OUT]" Все работает и, по-моему, достаточно просто

Добавлено: 01 Февраль 2006, 10:16
Andrew™
lsgsoftware писал(а):Профессиональное решение - прямая работа с ODBC -наверное самое правильное ( на то Андрей -SQL-профи).Но во-первых это очень муторно, и во-вторых есть мнение, что возникнут проблемы с ODBC-драйвером MYSQL(велосипедисты скорее всего этот драйвер не тестировали).
Позволю себе не согласится с утверждением.
Во первых, что такое ODBC - это определённого рода стандард команд со стороны клиента - КЛИЕНТ - ODBC - СЕРВЕР
КЛИЕНТ-ODBC - стандарт
ODBC-СЕРВЕР - тут уже специфика соответсвующего ODBC драйвера, на которую нам обращать внимания не требуется т к нам это не надо, нам надо реализовать только связку КЛИЕНТ-ODBC.

Во вторых, на первый взгляд всех пугает это ODBC API, огромное количество функций, с кучей параметров, чтобы препарировать курсор необходимо сделать не один вызов ODBC API функций, НО стоит всё это один раз завернуть в базовые объекты и использование становится очень простым и гибким, Вы можете сделать любой запрос к БД без всяких ограничений, чего не скажешь про FILE,DRIVER('ODBC'), где чтобы сделать какое то нестандартное не первый взгляд действие но простое, приходится очень шибко извращаться, декларируя фальшивые таблицы в DCT.
lsgsoftware писал(а): xxx{prop:sql}=' update table xxx set d=(select max(uid) from myfile);'
set(xxx);next(xxx)
и имеем xxx:d - идентификатор последней добавленной записи
Вроде все прозрачно, просто и работает
Коллеги, хотелось бы услышать Ваше мнение
ошыбочное решение, в многопользовательском режиме работы оно неправильное, т к с двух рабочих станций могут почти одновременно добавлять записи и послдедний SET NEXT вернёт не свой ID, а чужой, добавленный с другой рабочей станции.
Как я уже неоднократно говорил я за контролируемые процессы автонумерации, что это такое читайте на моём сайте.