powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Создал аналог функции openquery из MSSQL, правда работает только для select-a
4 сообщений из 4, страница 1 из 1
Создал аналог функции openquery из MSSQL, правда работает только для select-a
    #39577656
SlobAn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.

Может кому полезно будет и даже оптимизирует.
Минусы:
1) Файлы базы должны лежать в одной папке.
2) Процедура возвращает столбцы col1,col2,...,col10
3) Создает временные вьюшки и процедуры, но помоему по ним в FB нет ограницений.

Можно юзать так:
Код: sql
1.
2.
3.
4.
select t1.col1,t1.col2, t2.col1, t2.col2, t2.col3
from openquery('BASE1', 'select code, name from oktmo where id_s=12') t1,
     openquery('BASE2', 'select s.CODE, d.ZN1, d.DATE1 from data_269 d, oktmo s where d.DATE1=''22.08.2017'' and d.OKTMO=s.ID') t2
where t1.col1=t2.col1



Код: sql
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.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
CREATE PROCEDURE OPENQUERY(
    LINKED_RDB VARCHAR(30),
    LINKED_SQL VARCHAR(500))
RETURNS (
    COL1 VARCHAR(300),
    COL2 VARCHAR(300),
    COL3 VARCHAR(300),
    COL4 VARCHAR(300),
    COL5 VARCHAR(300),
    COL6 VARCHAR(300),
    COL7 VARCHAR(300),
    COL8 VARCHAR(300),
    COL9 VARCHAR(300),
    COL10 VARCHAR(300))
AS
declare variable SQL varchar(4000);
declare variable SQL1 varchar(4000);
declare variable SQL2 varchar(300);
declare variable SQL3 varchar(4000);
declare variable BASE_RDB varchar(30);
declare variable IDENT varchar(50);
declare variable TMP varchar(50);
declare variable FIELD_NAME varchar(30);
declare variable FIELD_TYPE varchar(50);
declare variable I integer;
begin
    ident = 'TMP_'||substring(replace(trim(uuid_to_char(gen_uuid())), '-','') from 1 for 10);
    select rdb$get_context('SYSTEM', 'DB_NAME') from rdb$database into :base_rdb;
    linked_rdb = reverse(substring(reverse(:base_rdb) from position('\' in reverse(:base_rdb))))||:linked_rdb||'.RDB';

    for execute statement 'select trim(RDB$RELATION_NAME) from RDB$RELATIONS where upper(trim(RDB$RELATION_NAME)) like ''TMP%VIEW'''
    ON EXTERNAL :linked_rdb
    WITH autonomous transaction
    into :tmp
    do
    begin
        sql = 'drop view '||:tmp;
        EXECUTE STATEMENT :sql ON EXTERNAL :linked_rdb WITH AUTONOMOUS TRANSACTION;
        when any do i = i + 1;
    end

    sql = 'create view '||:ident||'_VIEW as '||:linked_sql;
    EXECUTE STATEMENT :sql ON EXTERNAL :linked_rdb WITH AUTONOMOUS TRANSACTION;

    for select trim(RDB$PROCEDURE_NAME) from RDB$PROCEDURES where upper(trim(RDB$PROCEDURE_NAME)) like 'TMP%PROC' or upper(trim(RDB$PROCEDURE_NAME)) like 'TMP%PROC2'
    into :tmp
    do
    begin
        sql = 'drop procedure '||:tmp;
        EXECUTE STATEMENT :sql WITH AUTONOMOUS TRANSACTION;
        when any do i = i + 1;
    end

    sql = 'create procedure '||:ident||'_PROC
RETURNS (
    FIELD_NAME varchar(30),
    FIELD_TYPE varchar(50),
    FIELD_NULL varchar(10),
    ORD integer)
as
begin
for EXECUTE STATEMENT ''SELECT
TRIM(RF.RDB$FIELD_NAME) as FIELD_NAME,
CASE F.RDB$FIELD_TYPE
    WHEN 7 THEN
      CASE F.RDB$FIELD_SUB_TYPE
        WHEN 0 THEN ''''SMALLINT''''
        WHEN 1 THEN ''''NUMERIC('''' || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
        WHEN 2 THEN ''''DECIMAL('''' || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
      END
    WHEN 8 THEN
      CASE F.RDB$FIELD_SUB_TYPE
        WHEN 0 THEN ''''INTEGER''''
        WHEN 1 THEN ''''NUMERIC(''''  || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
        WHEN 2 THEN ''''DECIMAL(''''  || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
      END
    WHEN 9 THEN ''''QUAD''''
    WHEN 10 THEN ''''FLOAT''''
    WHEN 12 THEN ''''DATE''''
    WHEN 13 THEN ''''TIME''''
    WHEN 14 THEN ''''CHAR('''' || (TRUNC(F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER)) || '''') ''''
    WHEN 16 THEN
      CASE F.RDB$FIELD_SUB_TYPE
        WHEN 0 THEN ''''BIGINT''''
        WHEN 1 THEN ''''NUMERIC('''' || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
        WHEN 2 THEN ''''DECIMAL('''' || F.RDB$FIELD_PRECISION || '''', '''' || (-F.RDB$FIELD_SCALE) || '''')''''
      END
    WHEN 27 THEN ''''DOUBLE''''
    WHEN 35 THEN ''''TIMESTAMP''''
    WHEN 37 THEN ''''VARCHAR('''' || (TRUNC(F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER)) || '''')''''
    WHEN 40 THEN ''''CSTRING'''' || (TRUNC(F.RDB$FIELD_LENGTH / CH.RDB$BYTES_PER_CHARACTER)) || '''')''''
    WHEN 45 THEN ''''BLOB_ID''''
    WHEN 261 THEN ''''BLOB SUB_TYPE '''' || F.RDB$FIELD_SUB_TYPE
    ELSE ''''RDB$FIELD_TYPE: '''' || F.RDB$FIELD_TYPE || ''''?''''
END FIELD_TYPE,
TRIM(IIF(COALESCE(RF.RDB$NULL_FLAG, 0) = 0, '''''''', ''''NOT NULL'''')) as FIELD_NULL,
RF.RDB$FIELD_POSITION as ORD
FROM RDB$RELATION_FIELDS RF
JOIN RDB$FIELDS F ON (F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE)
LEFT OUTER JOIN RDB$CHARACTER_SETS CH ON (CH.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID)
LEFT OUTER JOIN RDB$COLLATIONS DCO ON ((DCO.RDB$COLLATION_ID = F.RDB$COLLATION_ID) AND (DCO.RDB$CHARACTER_SET_ID = F.RDB$CHARACTER_SET_ID))
WHERE (UPPER(RF.RDB$RELATION_NAME) in (UPPER('''''||:ident||'_VIEW'''')) ) AND (COALESCE(RF.RDB$SYSTEM_FLAG, 0) = 0)
ORDER BY RF.RDB$RELATION_NAME, RF.RDB$FIELD_POSITION''
ON EXTERNAL '''||:linked_rdb||'''
WITH autonomous transaction
into :FIELD_NAME, :FIELD_TYPE, :FIELD_NULL, :ORD
do SUSPEND;
end';
    EXECUTE STATEMENT :sql WITH AUTONOMOUS TRANSACTION;

    sql1 = '';
    sql2 = '';
    sql3 = '';
    i = 1;
    for execute statement 'select FIELD_NAME, FIELD_TYPE from '||:ident||'_PROC order by ORD'
    into :FIELD_NAME, :FIELD_TYPE
    do
    begin
        sql1 = :sql1||',col'||:i||' '||:field_type;
        sql2 = :sql2||',:col'||:i;
        sql3 = :sql3||',trim(cast('||:field_name||' as varchar(300)))';

        i = :i + 1;
        if (:i > 10) then break;
    end

    while (i < 11)
    do
    begin
        sql1 = :sql1||',col'||:i||' varchar(1)';
        sql2 = :sql2||',:col'||:i;
        sql3 = :sql3||',null as col'||:i;

        i = :i + 1;
    end

    sql = 'create procedure '||:ident||'_PROC2 RETURNS('||substring(:sql1 from 2)||')
as
begin
    for execute statement ''select '||substring(:sql3 from 2)||' from '||:ident||'_VIEW''
    ON EXTERNAL '''||:linked_rdb||'''
    WITH autonomous transaction
    into '||substring(:sql2 from 2)||'
    do SUSPEND;
end';

    EXECUTE STATEMENT :sql WITH AUTONOMOUS TRANSACTION;

    for execute statement 'select col1,col2,col3,col4,col5,col6,col7,col8,col9,col10 from '||:ident||'_PROC2'
    WITH autonomous transaction
    into :col1,:col2,:col3,:col4,:col5,:col6,:col7,:col8,:col9,:col10
    do SUSPEND;

    sql = 'execute block as begin if (exists(select * from RDB$RELATIONS where upper(RDB$RELATION_NAME)=upper('''||:ident||'_VIEW''))) then
           EXECUTE STATEMENT ''drop view '||:ident||'_VIEW'' WITH AUTONOMOUS TRANSACTION; END';
    EXECUTE STATEMENT :sql ON EXTERNAL :linked_rdb WITH AUTONOMOUS TRANSACTION;

    if (exists(select * from RDB$PROCEDURES where RDB$PROCEDURE_NAME=:ident||'_PROC')) then
    begin
        sql = 'drop procedure '||:ident||'_PROC';
        EXECUTE STATEMENT :sql WITH AUTONOMOUS TRANSACTION;
    end

end
...
Рейтинг: 0 / 0
Создал аналог функции openquery из MSSQL, правда работает только для select-a
    #39577671
Фотография Exteris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ахренеть ... в сад.
...
Рейтинг: 0 / 0
Создал аналог функции openquery из MSSQL, правда работает только для select-a
    #39577838
Filippov Dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SlobAn,
а зачем?
...
Рейтинг: 0 / 0
Создал аналог функции openquery из MSSQL, правда работает только для select-a
    #39578303
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А будешь плохо себя вести - заставим отлаживать предложенную выше вундервафлю.

SlobAnМинусы:4. "работать" может строго монопольно.

В чем сила, брат?
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Создал аналог функции openquery из MSSQL, правда работает только для select-a
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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