Sapforum.Biz
Инструменты => ABAP - Инструментальные средства => Тема начата: themax от Декабрь 07, 2016, 08:16:13 am
-
Доброго времени суток всем!
Не уверен, что выбрал именно ту ветку для этого поста, но т.к. связано с программированием пишу этот пост сюда. В общем суть моего вопроса такая: как возможно из sap делать запросы по изменению данных на прямую в таблицах, хранящихся не в sap, а непосредственно в sql server. Возможно ли это вообще? Если да, то может быть кто подскажет куда копать?
-
Если да, то может быть кто подскажет куда копать?
Копать в сторону оператора EXEC SQL и всего что с ним связано. Пример из справки ниже. Единственная проблема не всегда можно 100% отловить ошибку установления соединения, бывало, что соединение падало, а SAP говорил что все ОК, ну то уже такое редкое, но бывало. В 99% все работает без проблем.
EXEC SQL - CONNECT
A connection must be defined with the database before Native SQL statements can be used. When AS ABAP is started, a standard connection from the database interface to the central AS ABAP database is opened. This connection is defined as the current connection for embedded Native SQL statements and as a standard connection for Open SQL statements when an ABAP program is started. Use the following SAP-specific Native SQL statements, to start additional connections to other database systems. These connections can be accessed in static Native SQL.
The possible connections between AS ABAP and the database systems are defined in the database table DBCON. Entries in the database table DBCON can be created and modified using the DBA Cockpit tool.
Note
When the work process is switched, followed by an implicit database commit, then the commit is executed on all open connections.
Open Connection
Syntax
EXEC SQL.
CONNECT TO dbs [AS con]
ENDEXEC.
Effect
This static Native SQL statement opens a connection to the database system dbs and makes this the current connection. In other words, all the following Native SQL statements work with the database system named in dbs. If a connection to the specified database system already exists, then this is used; otherwise, a new connection is set up.
dbs can be specified as a literal or as a host variable containing a name from the column CON_NAME in the database table DBCON. The database system listed there must be supported by SAP and the technical data for the connection must be entered. The column DBMS in the database table DBCON contains an abbreviation for the type of database system.
The addition AS can be used to specify a name con for the connection. A literal or a character-like host variable can be specified for con. Its content is used as its name. The connection can then be selected using this name in the static Native SQL statement SET CONNECTION.
Selecting a Connection
Syntax
EXEC SQL.
SET CONNECTION {con|DEFAULT}
ENDEXEC.
Effect
This static Native SQL statement sets the current connection for all following static Native SQL statements. For con, a literal or a character-like host variable can be specified that must contain the name of a connection already started. The name of the connection can be specified either as the database system from the database table DBCON, as given in the static Native SQL statement CONNECT TO, or as the name assigned there using the AS addition. DEFAULT is used to set the standard connection to the central database system of the current AS ABAP.
Determining the Connection
Syntax
EXEC SQL.
GET CONNECTION :con
ENDEXEC.
Effect
This static Native SQL statement assigns the name of the current connection to con. con expects a character-like host variable. If the connection has been set up using the static Native SQL statement CONNECT TO and a name was given to the connection using AS, then this name is assigned. If the connection was set up without using a name assignment, the name of the database system from the database table DBCON is used. If the current connection is the standard connection to the central database of the AS ABAP, con is assigned the value "DEFAULT".
Close connection
Syntax
EXEC SQL.
DISCONNECT con
ENDEXEC.
Effect
This Native SQL statement closes the connection con. If con is not the current connection, this is not affected. If con is the current connection, the standard connection to the central database of the AS ABAP is simultaneously set as the current connection for all following static Native SQL statements.
For con, a literal or a character-like host variable can be specified that must contain the name of a connection already started. If a name was assigned while starting the connection using the static Native SQL statement CONNECT TO with the addition AS, then this name must be used. Otherwise, the name of the database system from the DBCON database table must be used. The standard connection "DEFAULT" cannot be closed.
Example
Starts a connection to an Oracle database and imports all entries of a column in the database table SCARR.
PARAMETERS dbs TYPE dbcon-con_name.
DATA carrid_wa TYPE scarr-carrid.
DATA dbtype TYPE dbcon_dbms.
SELECT SINGLE dbms
FROM dbcon
WHERE con_name = @dbs
INTO @dbtype.
IF dbtype = 'ORA'.
TRY.
EXEC SQL.
CONNECT TO :dbs
ENDEXEC.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_sy_native_sql_error.
ENDIF.
EXEC SQL.
OPEN dbcur FOR
SELECT carrid
FROM scarr
WHERE mandt = :sy-mandt
ENDEXEC.
DO.
EXEC SQL.
FETCH NEXT dbcur INTO :carrid_wa
ENDEXEC.
IF sy-subrc <> 0.
EXIT.
ELSE.
cl_demo_output=>write( |{ carrid_wa }| ).
ENDIF.
ENDDO.
EXEC SQL.
CLOSE dbcur
ENDEXEC.
EXEC SQL.
DISCONNECT :dbs
ENDEXEC.
CATCH cx_sy_native_sql_error.
MESSAGE `Error in Native SQL.` TYPE 'I'.
ENDTRY.
ENDIF.
cl_demo_output=>display( ).
-
О, тут нашелся пример, правда для ORACLE, но зато из рабочей системы:
DATA: con_name type dbcon_name value 'BSCS'.
EXEC SQL.
SET CONNECTION :con_name
ENDEXEC.
IF SY-SUBRC <> 0.
EXEC SQL.
CONNECT TO :con_name
ENDEXEC.
IF SY-SUBRC <> 0.
message i050(y_sav) with 'Установить соединение c BSCS не удалось'.
leave to screen 0.
ENDIF.
ENDIF.
*******
data: costat(9),
conum(10).
loop at ch_contr.
*** Здесь необходимо вставить проверочку db-connecta.
* clear ZBSCS_CONTR_ID.
* select single * from ZBSCS_CONTR_ID where CO_ID = ch_contr-contr.
*
* if sy-subrc <> 0 or ZBSCS_CONTR_ID-CH_STATUS = 'd'.
* message I050(y_sav)
* with 'Отсутствует BSCS-контракт: ОМ невозможен'.
* leave to screen 0.
* endif.
conum = ch_contr-contr.
EXEC SQL.
select ch_status
into :costat
from curr_co_status
where co_id = :conum
ENDEXEC.
if sy-subrc <> 0 or costat = 'd'.
EXEC SQL.
COMMIT
ENDEXEC.
* Close connection
EXEC SQL.
DISCONNECT :con_name
ENDEXEC.
message I050(y_sav)
with 'Отсутствует BSCS-контракт: ОМ невозможен'.
leave to screen 0.
endif.
endloop.
********
EXEC SQL.
COMMIT
ENDEXEC.
* Close connection
EXEC SQL.
DISCONNECT :con_name
ENDEXEC.
********
-
Доброго времени суток Всем.
Отвлекли меня немного от этой задачи, но я к ней вернулся. Уважаемый Uukrul, а Вы под кем коннектитесь с базе данных стороннего sql сервера?? Т.е. учётная запись какая используется, домена или самого sql сервера?? И ещё вопрос, откуда запросы пишутся?? Врятли это можно сделать из ABAP редаrтора se80 ??
-
Копать в сторону оператора EXEC SQL и всего что с ним связано. Пример из справки ниже. Единственная проблема не всегда можно 100% отловить ошибку установления соединения, бывало, что соединение падало, а SAP говорил что все ОК, ну то уже такое редкое, но бывало. В 99% все работает без проблем.
Мне не понятно как Ваш запрос понимает куда обращаться?
Вот например
Open Connection
Syntax
EXEC SQL.
CONNECT TO dbs [AS con] - как он понимает что за база такая dbs или нужно дополнительно делать настройки соединения с sql сервером, чтобы потом обращаясь к базе данных через запросы программа понимала куда именно обращаться??
ENDEXEC.
-
Ну как вам сказать, просто читаем все что написано внимательно, а не по диагонали. А там написана следующее:
The possible connections between AS ABAP and the database systems are defined in the database table DBCON. Entries in the database table DBCON can be created and modified using the DBA Cockpit tool.
Т.е. соединение нужно создать используя DBA Cockpit tool. Что это такое ищется на раз в гугле. Но, раз искать сложно то транзакция DBACOCKPIT. А уже там в дереве найдете в первой ветке "Database Connections" вот там и создаете свое соединение. В общем как-то так. Хотя конечно, это ваш администратор SAP системы должен делать.
-
Спасибо Uukrul.
Вроде бы получилось. Создал сначала соединение в DBA Cockpit tool, а затем указал его в программе.
data: iniciator(50)." type char.
data: dbs type dbcon-con_name.
dbs = 'TEST_ERP_SQL'.
EXEC SQL.
CONNECT TO :dbs
ENDEXEC.
EXEC SQL.
open Test_ERP_DB for
select Iniciator from Iniciators
endexec.
break-point.
do.
EXEC SQL.
FETCH NEXT Test_ERP_DB into :Iniciator
endexec.
IF sy-subrc <> 0.
EXIT.
ELSE.
BREAK-POINT.
ENDIF.
ENDDO.
break-point.
EXEC SQL.
CLOSE Test_ERP_DB
ENDEXEC.
-
Возник ещё один такой вопрос. Что касается выборки данных из сторонней базы sql сервера всё вроде бы понятно, есть стандартные вещи типа
EXEC SQL.
open Test_ERP_DB for
select Iniciator from Iniciators
endexec.
do.
EXEC SQL.
FETCH NEXT Test_ERP_DB into :Iniciator
endexec.
А вот что касается вставки данных в существующую табличку сторонней базы sql сервера. В теории где то читал, что можно использовать классы в abap для этих целей, но конкретно ничего пока не нашёл. Может кто подскажет куда копать дальше?
-
А вот что касается вставки данных в существующую табличку сторонней базы sql сервера. В теории где то читал, что можно использовать классы в abap для этих целей, но конкретно ничего пока не нашёл. Может кто подскажет куда копать дальше?
Вы работаете с языком запросов конкретной БД, вот им и добавляйте записей. А то что вы слышали это не об этом.
-
Хотите классы - копайте в сторону ADBC( ABAP Database Connectivity )
http://help.sap.com/abapdocu_702/en/abenadbc.htm (http://help.sap.com/abapdocu_702/en/abenadbc.htm)
-
Хотите классы - копайте в сторону ADBC( ABAP Database Connectivity )
http://help.sap.com/abapdocu_702/en/abenadbc.htm (http://help.sap.com/abapdocu_702/en/abenadbc.htm)
Не покатит к сожалению... так как там существует только доступ к внешним базам HANA, остальные пока отказать, насколько я помню. Кстати, нигде не нашел, планирует ли SAP вообще делать поддержку этого коннектора к другим СУБД.
PS: Сам когда нашел эту штуку обрадовааалсяяяяяя, а когда стал разбираться, оказалось не показалось.
-
Без проблем работает с любыми базами заведенными в дбконнекте.
-
Всем доброго времени суток!
Прошу прощение возможно за глупый вопрос, но столкнувшись с тонкостями написания sql языка в ABAP я не допонимаю как писать ту или иную часть кода. Казалось бы синтаксис простой, нооо...не срабатывает. При написании отчёта непосредственно в ABAP допустим с какой либо таблицы на селекционном экране выбора задаются условия в соответствии с которыми происходит селект с таблицы. Ну вот допустим пример select * from aufk appending corresponding fields of table tab
where auart in s_auart
and aufnr in s_aufnr
and erdat in s_erdat
and phas0 ne ''.
В этом коде видно, что на селекционном экране я могу заполнять поля, т.е. выбирать какие записи мне брать из таблиц, т.е. что я хочу этим сказать, а то что если я на селекционном экране заполню только одно из полей, например укажу Вид заказ ТОРО, то запрос выдаст мне список заказов с этим видом, а если два поля заполню, например вид заказа и номер заказа то запрос выдаст мне из таблицы aufk один заказ с видом и номером. Тоже самое пытаюсь сделать с внешней таблицей sql сервера. В ABAP указываю следующее selection-screen begin of block lb2 with frame title text-001.
parameters: year2 like tab-year obligatory,
r_num2 like tab-r_num,
ufio2 like tab-ufio.
selection-screen end of block lb2.
data: dbs type dbcon-con_name.
dbs = 'TEST_ERP_SQL'.
EXEC SQL.
CONNECT TO :dbs
ENDEXEC.
EXEC SQL.
open Test_ERP_DB for
select r_num, y_creat, ufio from Requests WHERE r_num = :r_num2
y_creat = :year2
endexec.
*break-point.
do.
EXEC SQL.
FETCH NEXT Test_ERP_DB into :tab-r_num, :tab-year, :tab-ufio
endexec.
if sy-subrc <> 0.
exit.
else.
append tab.
* break-point.
endif.
enddo.
break-point.
EXEC SQL.
CLOSE Test_ERP_DB
ENDEXEC.
При запуске и заполнении селекционного экрана всё отрабатывает и таблица заполняется согласно условиям, которые я указал на селекционном экране, но если я не заполняю хотя бы одно поле, например укажу год, чтобы произошла выборка всех записей из внешней таблицы за весь год, то условие не срабатывает. Не пойму, вроде бы синтаксис простой ABAPерский, но условия срабатывают только если я заполняю все поля на селекционном экране. Может быть кто нибудь подскажет что я не так делаю?!
-
Не пойму, вроде бы синтаксис простой ABAPерский, но условия срабатывают только если я заполняю все поля на селекционном экране. Может быть кто нибудь подскажет что я не так делаю?!
Ну правильно не срабатывает, если вы год не заполнили то поле год = space а таких заказов с таким годом нет. Это вы просто разбалованы конструкцией IN, которая в ABAP работает так, что если переменная пустая, то это условие просто выбрасывается из выборки, а не ищется запись со значением = space.
-
Ну правильно не срабатывает, если вы год не заполнили то поле год = space а таких заказов с таким годом нет. Это вы просто разбалованы конструкцией IN, которая в ABAP работает так, что если переменная пустая, то это условие просто выбрасывается из выборки, а не ищется запись со значением = space.
Спасибо Uukrul за раъёснение, всё таки нехватка знаний по языку sql даёт о себе знать, но всё же возник следующий вопрос. Мне нужно забрать данные с нескольких внешних таблиц Native SQL, связанных между собой одним полем, т.е. по сути мне нужен отчёт на ABAP, но не знание Open SQL в NAtive SQL ставит меня в тупик, потому как при попытке с генерировать простой код, прога падает в дамп и мне не понятно где именно не правильно. Прога отрабатывает нормально до второго EXEC SQL. Вот собственно код data cont_id(10).
selection-screen begin of block lb2 with frame title text-001.
parameters: year2 like tab-year obligatory,
r_num2 like tab-r_num.
selection-screen end of block lb2.
data: dbs type dbcon-con_name.
dbs = 'TEST_ERP_SQL'.
EXEC SQL.
CONNECT TO :dbs
ENDEXEC.
EXEC SQL.
open Test_ERP_DB for
select creat_date, r_num, req_sn, req_gn, req_dept, req_phone, req_pos, ufio, uid,
y_creat, cont_id from Requests WHERE r_num = :r_num2
endexec.
*break-point.
do.
EXEC SQL.
FETCH NEXT Test_ERP_DB into :tab-create_date, :tab-r_num, :tab-req_sn, :tab-req_gn,
:tab-req_dept, :tab-req_phone, :tab-req_pos, :tab-ufio, :tab-uid, :tab-year, :tab-cont_id
endexec.
if sy-subrc <> 0.
exit.
else.
append tab.
* break-point.
endif.
enddo.
loop at tab.
break-point.
EXEC SQL.
select creator_name into :tab-creator_name from creators WHERE cont_id = :tab-cont_id
endexec.
modify tab.
* break-point.
endloop.
break-point.
EXEC SQL.
CLOSE Test_ERP_DB
ENDEXEC.
Вот что я не правильно написал здесь?? В хелпе по exec sql в абапе только стандартный пример, но вот как быть в моём случае, когда нужно использовать несколько таблиц связанных друг с другом?? Буду весьма признательным за подсказку.
-
Прога отрабатывает нормально до второго EXEC SQL.
Если честно я даже не знаю какой у вас сервер СУБД, опять же если проблема с запросами на родном SQL к серверу, значит достаем руководство по SQL вашего сервера базы данных и читаем его. Код включенный между операторами EXEC SQL, вообще не проверяется системой SAP, а напрямую отдается в СУБД, следовательно надо читать правила работы с вашей СУБД.
-
Если честно я даже не знаю какой у вас сервер СУБД, опять же если проблема с запросами на родном SQL к серверу, значит достаем руководство по SQL вашего сервера базы данных и читаем его. Код включенный между операторами EXEC SQL, вообще не проверяется системой SAP, а напрямую отдается в СУБД, следовательно надо читать правила работы с вашей СУБД.
СУБД MS SQL Server 2008. Я просто подумал, что я может быть не правильно синтаксис пишу и Вы мне подскажите как правильно. Листал только что учебник Nilsen P. SQL Server 2005. Biblija polzovatelja.(Dialektika, 2008). Ничего похожего на построение нужного мне запроса пока не нашёл. Куда копать не понятно. В самом родном SQL Server я могу построить запрос с нескольких таблиц посредством этого одного общего поля и результат выдаётся в виде общей таблички, т.е. вроде бы как всё нормально, Но как написать этот запрос в sap abap мне не понятно.
-
Куда копать не понятно. В самом родном SQL Server я могу построить запрос с нескольких таблиц посредством этого одного общего поля и результат выдаётся в виде общей таблички, т.е. вроде бы как всё нормально, Но как написать этот запрос в sap abap мне не понятно.
Да вроде как точно так же перенесите код запроса в секцию EXEC SQL и должно отработать.
-
Да вроде как точно так же перенесите код запроса в секцию EXEC SQL и должно отработать.
Блин, затупил чота. В одном поле ошибся, исправил, теперь заработало, но возникает следом тут же вопрос, я конечно могу продублировать каждый loop at tab для каждой таблицы, с которой мне будут нужны какие то записи, а таблиц таких больше 40. На абапе с любой физической таблицы, лежащей в sap, такие вещи можно сделать либо с помощью inner join, либо с помощью for all entires. Просто я думаю как быстро у меня будет отрабатывать отчёт, если я все эти записи loop -ом буду забирать, а как здесь писать синтаксис допустим inner join мне чота не совсем понятно.
-
а как здесь писать синтаксис допустим inner join мне чота не совсем понятно.
Читаем документацию на язык SQL от МS, там JOIN точно должны быть. Еще раз, запрос передается на сервер базы данных в не измененном виде, так что проверку синтаксиса будет делать СУБД Microsoft SQL Server, так что данный вопрос наверное надо задавать специалистам по MS SQL.