powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / XML в ASA 9?
6 сообщений из 6, страница 1 из 1
XML в ASA 9?
    #33348436
Фотография Александр Гoлдун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ни разу еще не пользовал XML, только пытался играться и читал доки.
Понял, что можно результат выборки представить в виде XML. Понял, что
можно наоборот, сделать выборку из XML, в котором представлен набор записей.
А можно ли решить следующую задачу средствами XML: организовать для
таблицы некую возможность хранения произвольных значений и вытягивать
их? Например создаем таблицу с двумя полями: id и XML. В XML запихиваем
значения для псевдо-полей field1...fieldN. Хочется иметь возможность
менять их и селектить. Такое реализуемо? Куда смотреть?
Естественно, вопрос про реализацию этого на серверной стороне, а не
парсингом на клиенте.
Posted via ActualForum NNTP Server 1.3
...
Рейтинг: 0 / 0
XML в ASA 9?
    #33348514
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, запросто именно для таких игр и существует серверная функция OpenXML.
У меня уже больше года работает такая система: франчайзы генерируют на своих базах отчеты. Отчет в виде xml присылается в мою базу, и так же в виде xml и хранятся. А я уже на основе этих отчетов делаю свои собственные отчеты.

Отчет кладется в поле RepData таблички:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE "DBA"."Reports_Activity" (
	"FranId" char(4) NOT NULL,
	"RepId" char(10) NOT NULL,
	"Period" char(1) NULL COMPUTE( DBA.f_Get_PeriodCode_by_Dates(StartDate,EndDate) ),
	"StartDate" date NOT NULL,
	"EndDate" date NOT NULL,
	"PrepareDate" timestamp NOT NULL,
	"Version" char(10) NULL,
	"IsEmpty" bit NULL COMPUTE( (if(RepData is null) or(length(RepData) < 18) then 1 else 0 endif) ),
	"RepUID" "uniqueidentifier" NOT NULL DEFAULT newid(*),
	"RepData" "xml" NULL,
	PRIMARY KEY ( "RepUID" )
);

Вот пример xml:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<Report>
<row RepPart="1" PaymentMethod="Cash" sum="2859.0000"/>
<row RepPart="1" PaymentMethod="Checks & Transfers In" sum="8573.7000"/>
<row RepPart="1" PaymentMethod="Credit Cards" sum="7328.7000"/>
<row RepPart="1" PaymentMethod="Loans" sum="0.0000"/>
<row RepPart="4" RowId="3" Gross="18761.4000"/>
<row RepPart="4" RowId="2" Gross="0.0000"/>
<row RepPart="4" RowId="1" Gross="18761.4000"/>
<row RepPart="5"/>
<row RepPart="6" total_revenue="18761.4" total_exp="0" net_exp="18761.4"/>
<row RepPart="7" sum="0"/>
</Report>

А потом офисная клиентская программа на основе клиентских желаний (по датам, по кодам франчайзов и тд) выбирает UID'ы нужных отчетов, записывает их во временную глобальную таблицу и несколько раз запускает хранимую процедуру:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
CREATE PROCEDURE DBA.F005(in pRepPart numeric( 2 ))
BEGIN
	CASE pRepPart
	WHEN  1  THEN
		Select b.PaymentMethod, isnull(sum(b."sum"), 0 ) as "sum"
			from Reports_Activity a,
			LATERAL(Select PaymentMethod, sum
						FROM OpenXML(a.RepData, '/Report/row')
						with (RepPart integer '@RepPart',
			                  PaymentMethod char( 50 ) '@PaymentMethod',
            			      "sum" money '@sum')
						where RepPart= 1  and "sum" is not null) b
			where a.RepUID in (select RepUID from Requested_Reports)
			group by b.PaymentMethod;


	WHEN  2  THEN
		select b.TransactionType, isnull(sum(b."sum"), 0 ) as "sum"
			from Reports_Activity a,
			LATERAL(Select TransactionType, sum
						FROM OpenXML(a.RepData, '/Report/row')
						with (RepPart integer '@RepPart',
			                  TransactionType char( 50 ) '@TransactionType',
            			      "sum" money '@sum')
						where RepPart= 2  and "sum" is not null) b
			where RepUID in (select RepUID from Requested_Reports)
			group by TransactionType;
// и так далее для всех секций отчета. У каждой секции свой собственный набор полей в резалтсете.

	ELSE
// Клинтская программа запускает хранимку с нулевым кодом секции и получает количество секций в отчете этого типа.
		select  7 ;
	END CASE; 
	
END;
...
Рейтинг: 0 / 0
XML в ASA 9?
    #33349843
Фотография Александр Гoлдун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за пример, но подобное я уже в хелпах видел - хранение в поле по сути выборки. Мне бы что-нибудь попроще и более плоское.
Например делаю таблицу:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE dba.testxml(
  id integer not null,
  xmldata xml null,
  primary key(id)
)

INSERT INTO dba.testxml(id,xmldata)
VALUES( 1 ,'<product><qty>54</qty><color>Orange</color></product>')
Запрос, позволяющий вытянуть значения xml-полей:
Код: plaintext
1.
2.
SELECT * FROM testxml t, LATERAL( OPENXML( t.xmldata,'/product' )
WITH ( qty integer 'qty', color varchar( 20 ) 'color'))dt
Как проще всего организовать UPDATE этих псевдо-полей?
И еще вопрос про LATERAL, который я до этого тоже ни разу не использовал. Как с ним сделать что-то типа LEFT JOIN и т.п.
Поясню что я хочу. Добавим еще записи:
Код: plaintext
1.
2.
3.
4.
5.
6.
INSERT INTO dba.testxml(id,xmldata)
VALUES( 2 ,'<product></product>')
INSERT INTO dba.testxml(id,xmldata)
VALUES( 3 ,NULL)
INSERT INTO dba.testxml(id,xmldata)
VALUES( 4 ,'<other></other>')
Вышеприведенный select отберет только первые две записи, а записи 3 и 4 туда не попадут. Хочу чтоб попали.

P.S. Не все же время мне на чужие вопросы отвечать, побуду немного чайником
...
Рейтинг: 0 / 0
XML в ASA 9?
    #33350354
Фотография Александр Гoлдун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Видать, слишком чайниковские вопросы я задаю :)
Продолжим изыскания. Решил я сделать функцию для удобства извлечения значений из XML:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE FUNCTION "DBA"."xmlGetField"( in xmldata long varchar, in @path varchar( 40 ), in aname varchar( 40 ) )
RETURNS varchar( 40 )
BEGIN
    DECLARE @result varchar( 40 );
    SELECT FIRST res INTO @result FROM OPENXML( xmldata,@path )
    WITH ( res varchar( 40 ) aname);
    RETURN @result;
END
Ругается на "syntax error near aname on line 6"
Если прописать там константу
Код: plaintext
1.
    WITH ( res varchar( 40 ) 'something');
то все ОК. Но мне то константа как раз и не нужна, а нужен параметр. Оно принципиально не параметризуется или это просто недоработка в ASA?
И как быть тогда? Строить запрос динамически не очень хочется.
...
Рейтинг: 0 / 0
XML в ASA 9?
    #33350802
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Александр ГoлдунКак проще всего организовать UPDATE этих псевдо-полей?
По моему, там обновления не предусмотренно вообще :) На практике мне ни разу этого и не потребовалось. XML-данные приходят из какой-то сторонней базы до которой у меня в принципе не может быть доступа и я делаю только агрегирующие или простые выборки по ним.
Но в приниципе, можно внешнему селекту приписать ключевое слово FOR XML, результат селекта превратится в набор XML строк, склеиваем эти строки в один блоб и отправляем обратно в таблицу откуда брали данные :) Не особо просто и легко, но работать будет.


Александр ГoлдунВышеприведенный select отберет только первые две записи, а записи 3 и 4 туда не попадут. Хочу чтоб попали.
На третей и четвертой записях у тебя OpenXML не может открыть xml. На третьей записи вообще нечего открывать, а на четвертой оно не может найти ветку '/product' на нулевом уровне.
А вот почему оно работает как inner join я так и не понимаю до сих пор :(

Александр ГoлдунНо мне то константа как раз и не нужна, а нужен параметр.
Тоже не знаю. В BOL вроде запрета на переменные явно нету, но мне тоже не удалось использовать ничего кроме констант :( Кстати, обрати внимание что все пути и имена полей в OpenXML чувствительны к регистру даже если вся база регистро-нечувствительна!
...
Рейтинг: 0 / 0
XML в ASA 9?
    #33350859
Фотография Александр Гoлдун
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl
Но в приниципе, можно внешнему селекту приписать ключевое слово FOR XML, результат селекта превратится в набор XML строк, склеиваем эти строки в один блоб и отправляем обратно в таблицу откуда брали данные :) Не особо просто и легко, но работать будет.

Похоже, на клиенте это проще сделать. Например в Delphi каким-нибудь TXMLDocument
White Owl
Александр ГoлдунНо мне то константа как раз и не нужна, а нужен параметр.
Тоже не знаю. В BOL вроде запрета на переменные явно нету, но мне тоже не удалось использовать ничего кроме констант
Я смог обойти это по другому. Оказывается можно вместо конструкции:
Код: plaintext
1.
2.
SELECT FIRST res INTO @result FROM OPENXML( xmldata,'/product' )
    WITH ( res varchar( 40 ) 'color');
использовать следующую
Код: plaintext
1.
2.
SELECT FIRST res INTO @result FROM OPENXML( xmldata,'/product/color' )
    WITH ( res varchar( 40 ) 'text()');
Вместо '/product/color' можно подставить параметр, а 'text()' остается константой.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / XML в ASA 9?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]