Google

СУБД Oracle


Данная реализация DBFSQL для Oracle тестировалась с версией 8.1.6.

Чтобы построить приложение с использованием DBFSQL для Oracle его нужно слинковать с библиотекой libclip-oracle.so

Для подключения к серверу используйте конструктор класса TConnect в следующем синтаксисе:

ConnectNew("OR",NIL,NIL,<login>,<pwd>,[<dbname>]), где

"OR" - строка, идентифицирующая СУБД Oracle;

<login> - логин пользователя;

<pwd> - пароль пользователя.

<dbname> - имя базы данных (connect string);

Для связи записей набора (TRowset) и физической таблицы базы данных Oracle испольуется поле с с именем ROWID. Для полноценной работы с набором (с возможностью отражения производимых изменений набора записей в базе данных) в список запрашиваемых полей запроса SELECT следует явно включать зто поле.

В отличие от реализаций клиентов для других RDBMS (Postgres,MySQL), массив параметров оператора SQL должен иметь вид:

{ { <parname>, <parvalue>, <partype> } }

где <partype> тип данных Oracle. Символические имена типов определены в файле oracle.ch. Например:

rs := conn:CreateRowset("SELECT * FROM test WHERE name=:name",{{"name","Вова",ORT_VARCHAR2}})

В операторах автоматического отражения (deleteSQL и updateSQL, передаваемых конструктору TRowset) следует использовать предложение типа WHERE rowid=:rowid. Например:

DELETE FROM mytable WHERE rowid=:rowid

UPDATE mytable SET fname=:fname,lname=:lname WHERE rowid=:rowid

В операторе автоматического отражения insertSQL следует использовать предложение RETURNING rowid INTO :rowid. Это необходимо для дальнейшего изменения вновь добавленной записи в зтом же наборе данных. Например:

INSERT INTO mytable (fname,lname) VALUES (:fname,:lname) RETURNING rowid INTO :rowid

Библиотекой накладываются следующие ограничения:

1. Предложение RETURNING ... INTO ... понимается только для поля ROWID, и лишь в операторе insertSQL.

2. Не поддерживаются типы данных NAMED DATA TYPE (Object) и REF.

Возможно в следующих версиях библиотеки зти фичи будут реализованы.

Не рекомендуется использование типов CLOB и BLOB в связи с их гемморойностью. Вместо зтого следует использовать LONG VARCHAR и LONG RAW. О сложностях работы с полями LOB читайте руководство Oracle. Эти типы, включая и тип FILE, тем не менее реализованы и вы можете их использовать, руководствуясь правилами, описанными Oracle.

Реализованы следующие типы Oracle:
Тип Oracle             Тип Clipper

VARCHAR2 CHARACTER CHAR CHARACTER RAW CHARACTER NUMBER NUMERIC INTEGER NUMERIC FLOAT NUMERIC LONG CHARACTER LONG VARCHAR CHARACTER LONG RAW CHARACTER DATE DATE CLOB CHARACTER BLOB CHARACTER FILE CHARACTER

В качестве простейшего примера использования SQL с СУБД Oracle в комплект поставки включен файл mysqlplus.prg, функционально дублирующий утилиту sqlplus из комплекта поставки Oracle. Вот ее текст:
PROCEDURE Main()

LOCAL conn,rs,data
LOCAL sql := ""
LOCAL I := 1
LOCAL user := "scott"	// -u
LOCAL passwd := "tiger"	// -p
LOCAL db := ""			// -d

ErrorBlock({|e| SQLError(e)})
DO WHILE param(I) != NIL
	IF param(I) == "--help" .OR. param(I) == "-?"
		? "mysqlplus  Ver 0.01 for Oracle Distrib 8.1.6, for pc-linux-gnu (i686)"
		? "By ITK Ltd., by Rusty"
		? "This software comes with ABSOLUTELY NO WARRANTY."
		?
		? "Usage: mymysql [OPTIONS]"
		?
		? "  -?, --help     Display this help and exit"
		? "  -u             User for login if not current user"
		? "  -p             Password to use when connecting to server"
		? "  -d             Database to work with"
		?
		QUIT
	ELSEIF param(I) == "-u"
		user := param(++I)
	ELSEIF param(I) == "-p"
		passwd := param(++I)
	ELSEIF param(I) == "-d"
		db := param(++I)
	ENDIF
	I++
ENDDO

CLS

BEGIN SEQUENCE
	conn := ConnectNew("OR",NIL,NIL,user,passwd,db)
RECOVER USING e
	QUIT
END SEQUENCE

DO WHILE UPPER(sql := GetCommand()) != "Q"
	IF UPPER(LEFT(sql,6))=="SELECT"
		sql := LEFT(sql,LEN(sql)-1)
		BEGIN SEQUENCE
			rs := conn:CreateRowset(sql)
		RECOVER USING e
			LOOP
		END SEQUENCE
		FOR I:=1 TO rs:NFields()
			?? PADR(rs:FieldName(I),10),"|"
		NEXT
		?
		FOR I:=1 TO rs:NFields()
			?? "----------","|"
		NEXT
		DO WHILE !rs:Eof()
			?
			data := rs:Read()
			FOR I:=1 TO rs:NFields()
				tmp := data[HASHSTR(UPPER(rs:FieldName(I)))]
				IF tmp==NIL
					?? "NIL       ","|"
				ELSE
					?? PADR(data[HASHSTR(UPPER(rs:FieldName(I)))],10),"|"
				ENDIF
			NEXT
			rs:Skip()
		ENDDO
		rs:Destroy()
	ELSE
		BEGIN SEQUENCE
			?? LEFT(sql,LEN(sql)-1)+": "
			conn:Command(sql,NIL)
			?? "OK"
		RECOVER USING e
			LOOP
		END SEQUENCE
	ENDIF
	?
ENDDO
conn:Destroy()

RETURN

FUNCTION GetCommand()
	LOCAL ret := ""
	LOCAL tmp := ""
	LOCAL first := .T.

	@ MAXROW(),0 SAY ""
	DO WHILE !(";" $ tmp) .AND. ALLTRIM(UPPER(ret)) != "Q"
		IF first
			ACCEPT "SQL> " TO tmp
			first := .F.
		ELSE
			ACCEPT "SQL---> " TO tmp
		ENDIF
		ret += tmp + " "
	ENDDO
RETURN ALLTRIM(ret)

FUNCTION SQLError(e)
	?? e:operation
	BREAK(e)
RETURN NIL