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

ODBC

Модератор: Andrew™

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
lsgsoftware
Ветеран
Сообщения: 311
Зарегистрирован: 08 Июль 2005, 22:04

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

Сообщение 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, штатно такого нет
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3134
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 10 раз
Поблагодарили: 28 раз
Контактная информация:

Сообщение Дед Пахом »

myfile{prop:sql}='insert into myfile set name=''' & clip(s) &''''
так не работает?

'select 2*2' можно выполнить вроде только как {prop:sql}=, поэтому без файла не обойтись.
С уважением, ДП
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

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

Сообщение 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
lsgsoftware
Ветеран
Сообщения: 311
Зарегистрирован: 08 Июль 2005, 22:04

Сообщение 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}.
Заранее благодарен
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3134
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 10 раз
Поблагодарили: 28 раз
Контактная информация:

Сообщение Дед Пахом »

Вообще говоря, есть такая технология:
заводим в словаре один файл с одним полем 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)
С уважением, ДП
lsgsoftware
Ветеран
Сообщения: 311
Зарегистрирован: 08 Июль 2005, 22:04

Сообщение 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 - идентификатор последней добавленной записи
Вроде все прозрачно, просто и работает
Коллеги, хотелось бы услышать Ваше мнение
PV
Новичок
Сообщения: 5
Зарегистрирован: 31 Январь 2006, 9:00

Сообщение 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]" Все работает и, по-моему, достаточно просто
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Сообщение 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, а чужой, добавленный с другой рабочей станции.
Как я уже неоднократно говорил я за контролируемые процессы автонумерации, что это такое читайте на моём сайте.
Ответить