Universal function module to retrieve SAP table data - select

What is the best way to access table data from a SAP system?
I tried it with it RFC_READ_TABLE, but this RFC returns the data in concatenated form within a single column and has a size restriction for row data.
Is there a better way to access SAP data in generic form without creating custom RFCs into the system?
I am searching for a standard RFC solution, not a custom script.

If I understand your question right, you want to read a table, but at time of programming, you don't know which table.
With Select * from (tablename)you can read with a dynamic table name.
The target field can be defined dynamic with create data.
An example (untested, currently I have no access to an SAP-system):
DATA: lv_tablename TYPE string,
ev_filelength TYPE i.
lv_tablename = 'mara'. "e.g. a parameter
DATA dref TYPE REF TO data.
CREATE DATA dref TYPE TABLE OF (lv_tablename).
FIELD-SYMBOLS: <wa> TYPE ANY TABLE.
ASSIGN dref->* to <wa>.
SELECT * FROM (lv_tablename) INTO TABLE <wa>. "Attention for test, may be large result
"<wa> is like a variable with type table mara

TYPES: BEGIN OF t_bseg,
*include structure bseg.
bukrs LIKE bseg-bukrs,
belnr LIKE bseg-belnr,
gjahr LIKE bseg-gjahr,
buzei LIKE bseg-buzei,
mwskz LIKE bseg-mwskz, "Tax code
umsks LIKE bseg-umsks, "Special G/L transaction type
prctr LIKE bseg-prctr, "Profit Centre
hkont LIKE bseg-hkont, "G/L account
xauto LIKE bseg-xauto,
koart LIKE bseg-koart,
dmbtr LIKE bseg-dmbtr,
mwart LIKE bseg-mwart,
hwbas LIKE bseg-hwbas,
aufnr LIKE bseg-aufnr,
projk LIKE bseg-projk,
shkzg LIKE bseg-shkzg,
kokrs LIKE bseg-kokrs,
END OF t_bseg.
DATA: it_bseg TYPE STANDARD TABLE OF t_bseg INITIAL SIZE 0,
wa_bseg TYPE t_bseg.
DATA: it_ekko TYPE STANDARD TABLE OF ekko.
*Select all fields of a SAP database table into in itab
SELECT *
FROM ekko
INTO TABLE it_ekko.

Try this snippet of RFC_READ_TABLE to get data in structured form:
DATA: oref TYPE REF TO cx_root,
text TYPE string,
obj_data TYPE REF TO data.
lt_options TYPE TABLE OF rfc_db_opt,
ls_option TYPE rfc_db_opt,
lt_fields TYPE TABLE OF rfc_db_fld,
ls_field TYPE rfc_db_fld,
lt_entries TYPE STANDARD TABLE OF tab512.
FIELD-SYMBOLS: <fs_tab> TYPE STANDARD TABLE.
TRY.
ls_option-text = `some query`.
APPEND ls_option TO lt_options.
ls_field-fieldname = 'PARTNER'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'TYPE'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'BU_GROUP'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'BU_SORT1'.
APPEND ls_field TO lt_fields.
ls_field-fieldname = 'TITLE'.
APPEND ls_field TO lt_fields.
CALL FUNCTION 'RFC_READ_TABLE' DESTINATION dest
EXPORTING
query_table = 'BUT000'
TABLES
options = lt_options
fields = lt_fields
data = lt_entries.
CATCH cx_root INTO oref.
text = oref->get_text( ).
MESSAGE text TYPE 'E'.
ENDTRY.
IF lt_entries IS NOT INITIAL.
CREATE DATA obj_data TYPE TABLE OF but000.
ASSIGN obj_data->* TO <fs_tab>.
CREATE DATA obj_data TYPE but000.
ASSIGN obj_data->* TO FIELD-SYMBOL(<fs_line>).
LOOP AT lt_entries ASSIGNING FIELD-SYMBOL(<wa_data>).
LOOP AT lt_fields ASSIGNING FIELD-SYMBOL(<fs_fld>).
ASSIGN COMPONENT <fs_fld>-fieldname OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<lv_field>).
IF <lv_field> IS ASSIGNED AND sy-subrc IS INITIAL.
<lv_field> = <wa_data>-wa+<fs_fld>-offset(<fs_fld>-length).
ENDIF.
APPEND <fs_line> TO <fs_tab>.
ENDLOOP.
ENDLOOP.
ENDIF.
IF <fs_tab> IS NOT INITIAL.
"Bingo!
ENDIF.

Related

How to do a table property validation in Matlab?

When I create an object in a constructor,
myTable property is constructed on the fly, for example, from csv file. I want to have some validation for that property as I have for myInt.
Do you happen to know how to do that? In the future, I guess I will need a per-column validation...
classdef BigObject
properties
myInt (1,1) double {mustBeNonnegative, mustBeInteger} = 0;
myTable (?,?) table {mustBeGreaterThan(table{1}.Variables,1), mustBeLessThan(table{2} ? ,2)} = table;
I tried selecting columns
myTable table {mustBeGreaterThan(table{1},1)} = table;
myTable table {mustBeGreaterThan(table{2}.Variables,2)} = table;
myTable table {mustBeGreaterThan(table.Variables,3)} = table;
The best way to achieve this is to write your own simple property validation function. You can build this on top of existing functions. So, you might do something like this:
%% Base case - passes
t = table((1:10).', 'VariableNames',{'MyVar'});
someFcn(t);
%% Fails because value is negative
t2 = table(-(1:10).', 'VariableNames',{'MyVar'});
someFcn(t2)
% Example function that uses validation
function someFcn(t)
arguments
t {mustHavePositiveVar(t, 'MyVar')}
end
end
% Custom validation function
function mustHavePositiveVar(t, varName)
try
mustBeA(t, 'table');
mustBeMember({varName}, t.Properties.VariableNames)
mustBePositive(t.(varName));
catch E
error('Input must be a table with a variable named %s that is all positive', varName)
end
end
Note there's a nuance if you use the class constraint syntax at the same time as a property validation function - namely that the property gets assigned and type-coerced before the validation functions run. So if you're going to validate the type of an input, you need to omit the class constraint (otherwise the input might simply be coerced to the correct type anyway).

How to pick up data from row and put it into tPostgresqlInput?

I have a requets which giving me an ids. I need to iterate them into another request, so I have a sheme like this: scheme
In tPostgresqlInput I have this code rc.id = upper('18ce317b-bf69-4150-b880-2ab739eab0fe') , but instead of id I need to put smthn like globalMap.get(row4.id). How did I do this?
Apparently this is a syntax issue
Try with :
"select * FROM table LEFT JOIN table on parameter JOIN table on parameter
WHERE 1=1 AND
column = 'content'
AND upper(rc.id) = upper('"+((String)globalMap.get("row4.id")) +"')"
Expressions in tDBInput should always begin and end with double quotes.
Don't forget to cast globalMap.get() with the type of your element (here I put String)
.equals is not a DB function but a java function. I have replaced it with '='
Let me know if it's better

Is it possible to convert table data to similar type using VALUE operator

I think this question is best illustrated with an example. I've got 2 tables of different data types (but table_type1 is easily convertable to table_type2)
i_tab1 type table_type1 (fields: matnr,maktx,spras)
i_tab2 type table_type2 (fields: mandt,matnr)
Is it possible to use the VALUE operator, possibly with FOR line in i_tab1 (or maybe a similar inline commands) to convert and transfer data of i_tab1 to i_tab2 ? I was thinking of something like the following:
i_tab2 = VALUE # (for line in i_tab1
BASE = gt_itab2 (
MANDT = sy-mandt;
MATNR = line-matnr
)
).
You were close. Here is a solution you might find helpful.
REPORT ZZZ.
TYPES: BEGIN OF tab1_line,
matnr TYPE mara-matnr,
maktx TYPE makt-maktx,
spras TYPE makt-spras,
END OF tab1_line,
BEGIN OF tab2_line,
mandt TYPE t000-mandt,
matnr TYPE mara-matnr,
END OF tab2_line,
table_type1 TYPE STANDARD TABLE OF tab1_line WITH EMPTY KEY,
table_type2 TYPE STANDARD TABLE OF tab2_line WITH EMPTY KEY.
DATA:
g_tab1 TYPE table_type1,
g_tab2 TYPE table_type2.
START-OF-SELECTION.
g_tab2 = VALUE #( BASE g_tab2 FOR i IN g_tab1 ( mandt = sy-mandt matnr = i-matnr ) ).

c# using Enterprise-Library

How we can pass data table to stored procedure in c# using Enterprise library ?
I am using command
cmd.AddInParameter(objDbCommand, DBAccessDetails.dataTablePrm, SqlDbType.Structured, curatedListprm);
then coming issue as :
Conversion failed when converting the nvarchar value 'ZAQ' to data type int.
The data for table-valued parameter "#data" doesn't conform to the table type of the parameter. SQL Server error is: 245, state: 1
Plz tell me what I do and what is issue ?
First you need to have created your user defined table type
CREATE TYPE [schema].[tableName] AS TABLE(
table columns and types )
GO
then you need to create your stored proc to take the table valued parameted
create procedure procName
(
#tvp dbo.tableNamereadonly
)
then you need to pass your datatable in via .Net with something like this
var param = new SqlParameter("#tvp" Sqldbtype.Structured);
param.Value = {your data table}

How to create and store array of objects in postgresql

In postgresql allowed array types or integer and text.But i need to create array of objects.how can i do that.
myarray text[]; //for text ['a','b','c']
myarray integer[]; //for integer[1,2,3]
I need to create the array like below
[{'dsad':1},{'sdsad':34.6},{'sdsad':23}]
I dont want to use JSON type.Using array type i need to store the array of objects.
If you're running Postgres 9.2+, you can use the JSON type.
For example, we could do
create table jsontest (id serial primary key, data json);
insert into jsontest (data) values ('[{"dsad":1},{"sdsad":34.6},{"sdsad":23}]');
And query the data with
select data->1 from jsontest;
{"sdsad":34.6}
You say:
I dont want to use JSON type
but you cannot use an ordinary array, as PostgreSQL arrays must be of homogenous types. You can't have a 2-dimensional array of text and integer.
What you could do if you don't want to use json is to create a composite type:
CREATE TYPE my_pair AS (blah text, blah2 integer);
SELECT ARRAY[ ROW('dasd',2), ROW('sdsad', 34.6), ROW('sdsad', 23) ]::my_pair[]
which will emit:
array
----------------------------------------
{"(dasd,2)","(sdsad,35)","(sdsad,23)"}
(1 row)
If you don't want that, then json is probably your best bet. Or hstore:
SELECT hstore(ARRAY['a','b','c'], ARRAY[1,2,3]::text[])
hstore
------------------------------
"a"=>"1", "b"=>"2", "c"=>"3"
(1 row)
JSON is your preferred answer, but more info as to why.
You can do something like:
SELECT array_agg(v)
FROM mytable v;
However you get something that looks like this:
{"(dsad,1)","(sdsad,34.6)","(""sdsad,var"",23)"}
It is then up to you to know how to decode this (i.e. column order). This is possible to do programmatically but is much easier with JSON.
It's hacky, but what about using an array for each property in the object (and its corresponding scalar type). If you have a data model layer in your get/read you could put the arrays "back together" into an array of objects and in your save method you would break you objects apart into synchronized arrays. This might be complicated by your example of each object not having the same properties; IDK how you'd store undefined for a property unless you're willing for null to be the same semantically.
It's not entirely clear if you mean json:
# select '[{"dsad":1},{"sdsad":34.6},{"sdsad":23}]'::json;
json
------------------------------------------
[{"dsad":1},{"sdsad":34.6},{"sdsad":23}]
(1 row)
Or an array of json:
# select array['{"dsad":1}', '{"sdsad":34.6}', '{"sdsad":23}']::json[];
array
------------------------------------------------------
{"{\"dsad\":1}","{\"sdsad\":34.6}","{\"sdsad\":23}"}
(1 row)
Or perhaps hstore? If the latter, it's only for key-values pairs, but you can likewise use an array of hstore values.
You can do something like:
SELECT JSON_AGG(v) FROM mytable v;
However you get something that looks like this:
["00000000-0000-0000-0000-000000000001","00000000-0000-0000-0000-000000000002", "00000000-0000-0000-0000-000000000003"]
exemple :
SELECT title, (select JSON_AGG(v.video_id) FROM videos v WHERE v.channel_id = c.channel_id) AS videos FROM channel AS c
Use text[] myarray insted of myarray text[].