SELECT FROM #itab causes syntax error. Why? - abap

I try to use SELECT FROM #itab like explained here in SAP docs.
I have never used this feature, but think this is great. You can query a internal data structure which just exists in the RAM of the interpreter like it would be a real table in the database. I am impressed.
Here is the ABAP code:
data: lt_get_auth_values TYPE STANDARD TABLE OF US335.
CALL FUNCTION 'GET_AUTH_VALUES'
EXPORTING
OBJECT1 = 'Z:FOO'
USER = sy-uname
TABLES
VALUES = lt_get_auth_values.
SELECT highval from #lt_get_auth_values as mytab WHERE field = 'WERKS'
INTO TABLE #DATA(static_perm_filter_fields).
I can't active the function because "from #lt_get_auth_values" is a syntax error according to my system.
What's wrong with this line?
SAP Version: 740 (sorry, it first I thought it was 752)

SELECT ... FROM #itab appeared in 7.52 so it should work.
On my 7.52 system it works but you must indicate a table alias. There's an example in the ABAP documentation (cf first link above).

Related

Select last 30 days rows from MARA using SSIS

I'm trying to select rows for last date change = 30 days.
I tried LAEDA = ( sy-datum -30 ) in where clause, but it always generated error.I connect to sap Abap database.
The message error:
[EIS-Material 1] Error: ERPConnect.ERPException: Error while
receiving function return values: SYSTEM_FAILURE An error has occurred
while parsing a dynamic entry. at
ERPConnect.RFCAPI.ReceiveFunctionResults(UInt32 connectionHandle,
RFC_PARAMETER[] importing, RFC_PARAMETER[] changing, RFC_TABLE[]
tables, Encoding apiEncoding) at
ERPConnect.RFCFunction.ReceiveFunctionArguments(RFC_TABLE[]&
apiTables) at ERPConnect.RFCFunction.CallClassicAPI() at
ERPConnect.RFCFunction.ExecuteRFC(Byte[] tid) at
XtractKernel.Extractors.TableExtractor.GetPackage(RFCFunction& func)
at XtractKernel.Extractors.TableExtractor.Extract() at
XtractKernel.Extractors.ExtractorBase`1.Extract(ProcessResultCallback
processResult) at XtractIS.XtractSourceTable.PrimeOutput(Int32
outputs, Int32[] outputIDs, PipelineBuffer[] buffers) at
Microsoft.SqlServer.Dts.Pipeline.ManagedComponentHost.HostPrimeOutput(IDTSManagedComponentWrapper100
wrapper, Int32 outputs, Int32[] outputIDs, IDTSBuffer100[] buffers,
IntPtr ppBufferWirePacket)
So you are using a third party tool to extract data from an SAP system. According to the error message, the toole makes a Remote Function Call (RFC) and handing the SQL to the ABAP backend. Then your where condition must be valid ABAP/Open SQL syntax, regardless of the database behind.
Your call (simplified) would look like this in ABAP (with new #-syntax):
DATA(lf_dat) = sy-datum - 30.
SELECT matnr
FROM mara
WHERE laeda >= #lf_dat
INTO TABLE #DATA(lt_matnr)
.
The problem is, that you are not allowed to make this calculation within the the statement, as far as I know, so you have to use a variable. But since your third party tool only allows you to write a where condition I see no way to handle this, except with a static date in the condition:
laeda >= '20190106' "YYYYMMDD
You can add the ABAP tag to your question to attract more specialists on this ABAP specific topic.
I see in the Xtract IS online help that there's a custom function module named Z_THEO_READ_TABLE installed at ABAP side, which executes the SQL sent by Xtract IS. The module is provided in 2 flavors, one being for ABAP >= 740 SP 5, so I guess it's a version for ABAP SQL Strict Mode.
So, I thought that maybe you could write this ABAP-like Where Clause by using a "host expression", which is valid in ABAP SQL Strict Mode :
LAEDA = #( sy-datum - 30 )
Based on the error message you have, "An error has occurred while parsing a dynamic entry", I guess that this function module does something like SELECT (dyn-columns) FROM (dyn-table) WHERE (dyn-condition), i.e. all elements are dynamically defined at run time.
Unfortunately, the "ABAP documentation sql_cond - (cond_syntax) says that "Host expressions are not allowed in dynamic logical expressions."
So long, impossible to make a where clause as you wish.
There are probably many ways to get around this limit (like creating a SAPquery or BAPI in SAP and calling it from Xtract IS, etc.) but that's another question.
In mySQL / MariaDB, this works:
select ...
from ...
where date >= DATE_ADD(CURDATE(), INTERVAL -30 DAY)
but we need to know what database you are working with.
You may try it, if you use SQL database:
Select DATEADD(Month, -1, getdate())
You cannot specify ABAP formula like that through SAP Open SQL.
Not to directly resolve your challenge (as you have product limitation), here is how dynamic filter is achieved through AecorSoft tool:
(DT_WSTR, 4)(DATEPART("yy" , GETDATE())) + RIGHT("0" + (DT_WSTR, 4)DATEPART("mm" , GETDATE()),2) + RIGHT("0" + (DT_WSTR, 4)DATEPART("dd" , GETDATE()),2)
For complete use case, you can check the blog SAP Table Delta Extract Made Easy through Dynamic Filters

F#: Cannot call stored procedure on MariaDB database using SQLProvider

I adapted my code from the instructions here.
open FSharp.Data.Sql
let [<Literal>] connection_str = "Server=localhost;Port=3306;SSL Mode=None;Uid=<UID>;Pwd=<PWD>;Database=<DB>"
type provider = SqlDataProvider<Common.DatabaseProviderTypes.MYSQL, connection_str>
let context = provider.GetDataContext()
context.Procedures.SpGetFrontContracts.Invoke(1)
Intellisense works until the period after SpGetFrontContracts. After that, nothing. Trying to compile, I get:
Error FS0039 The field, constructor or member 'Invoke' is not defined.
I am otherwise able to connect to the database and insert and query data, as long as I stick to tables and views.
SpGetFrontContracts is a valid stored procedure in my database (its actual name is sp_get_front_contracts, but the type provider seems to remove underscores). I can run it successfully using HeidiSQL. In case it's useful, here's the create code:
CREATE DEFINER=`<UID>`#`localhost` PROCEDURE `sp_get_front_contracts`(
IN `Group` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
SELECT p.DateTime, p.Contract, p.Volume, c.Name
FROM tbl_contract_price_data p
INNER JOIN tbl_contracts c on p.Contract = c.ID
WHERE c.`Group` = `Group`
ORDER BY p.DateTime
LIMIT 1000;
END
I tried creating a simpler sproc that was named 'test', took no parameters, and simply ran a select statement. It showed up in the type provider under Procedures, but again I could not call Invoke on it.
My best guess is that Invoke is being inherited from some namespace or assembly reference I don't have, so I'm currently looking through the SqlProvider source to try to figure out what it might be. I'm currently referencing:
FSharp.Core
FSharp.Data
FSharp.Data.SqlProvider
mscorlib
System
System.Core
System.Data
System.Numerics
System.ValueTyple
System.Xml.Linq
Thank you for any suggestions.
Edit: It looks like the action is in SqlDesignTime.fs in a function called generateSprocMethod that starts on line 346. I'll try to figure out what's going on in there.
Edit: After three days banging my head against this, I gave up and just used MySQL Connector/NET.
I'm not sure about your underlying data or structures, but I know these are two other (correct) ways to solve it:
WHERE c.`Group` = `Group` -- what you have.
-- possible corrections:
WHERE c.`Group` = p.`Group` -- did you mean this?
WHERE c.`Group` = "Group" -- or this?

Using PosgreSQL array_agg with join alias in JOOQ DSL

I want to convert this SQL query to JOOQ DSL.
select "p".*, array_agg("pmu") as projectmemberusers
from "Projects" as "p"
join "ProjectMemberUsers" as "pmu" on "pmu"."projectId" = "p"."id"
group by "p"."id";
Currently i have tried doing something like this using JOOQ:
val p = PROJECTS.`as`("p")
val pmu = PROJECTMEMBERUSERS.`as`("pmu")
val query = db.select(p.asterisk(), DSL.arrayAgg(pmu))
.from(p.join(pmu).on(p.ID.eq(pmu.PROJECTID)))
.groupBy(p.ID)
This does not work because DSL.arrayAgg expects something of type Field<T> as input.
I am new to JOOQ and not an SQL professional. Detailed explanations and impovement suggestions are highly appreciated.
First of all, the syntax indeed works, checked this in SQL Fiddle: http://sqlfiddle.com/#!17/e45b7/3
But it's not documented in detail: https://www.postgresql.org/docs/9.5/static/functions-aggregate.html
https://www.postgresql.org/docs/current/static/rowtypes.html#ROWTYPES-USAGE
That's probably the reason jOOQ doesn't support this currently: https://github.com/jOOQ/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/DSL.java#L16856
The only syntax that will work currently is with a single field: DSL.arrayAgg(pmu.field(1))
What you're looking for is a way to express PostgreSQL's "anonymous" nested records through the jOOQ API, similar to what is requested in this feature request: https://github.com/jOOQ/jOOQ/issues/2360
This is currently not possible in the jOOQ API as of version 3.11, but it definitely will be in the future.
Workaround 1
You could try using the experimental DSL.rowField() methods on a Row[N]<...> representation of your table type. This may or may not work yet, as the feature is currently not supported.
Workaround 2
A workaround is to create a type:
create type my_type as (...) -- Same row type as your table
And a view:
create view x as
select "p".*, array_agg("pmu"::my_type) as projectmemberusers
from "Projects" as "p"
join "ProjectMemberUsers" as "pmu" on "pmu"."projectId" = "p"."id"
group by "p"."id";
And then use the code generator to pick up the resulting type.

Where is the BigQuery documentation describing how to define a Javascript UDF function inline in SQL (not in the UDF editor or a separate file)?

In this other question https://stackoverflow.com/a/36145155/2259571 a code example was posted that defines a Javascript UDF function inline, not in the BigQuery UI UDF Editor, not in a bq command-line --udf_resource option, but loaded directly from the text of the SQL query.
Where in the BigQuery documentation can I find more info about how this is done?
JS(...) looks like a function but I cannot find it in the documentation at https://cloud.google.com/bigquery/query-reference I also cannot find anything about this construct in https://cloud.google.com/bigquery/user-defined-functions Am I just missing it? Or is it undocumented?
Here is a simplified version of the query (this runs in the BigQuery UI and in the bq command line tool):
SELECT outputA
FROM JS(
// input table
(
SELECT text2 as inputA
FROM
(SELECT 'mikhail' AS text2),
(SELECT 'mike' AS text2),
(SELECT 'michael' AS text2),
(SELECT 'javier' AS text2),
(SELECT 'thomas' AS text2)
)
// input columns
, inputA
// output schema
, "[{name: 'outputA', type:'string'}]"
// function
, "function(r, emit) {
emit({
outputA: 'XX ' + r.inputA + ' XX'
});
}"
)
Output:
outputA
XX mikhail XX
XX mike XX
XX michael XX
XX javier XX
XX thomas XX
Update 2022-03-31: BigQuery recommends using standard SQL, which includes the following syntax for inline JS UDFs:
https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions
The inline JS syntax is the "alpha" syntax and is deliberately left undocumented. We currently have no plans to remove or change this functionality, but it's also not an officially supported feature.
We do have plans to provide official support for inline JS UDFs at some point in the future, but with a slightly different syntax.
If you'd like to use this feature despite the caveat above, see Mikhail's answer.
I see now what you are looking for.
Looks like this is not available in google bigquery documentation
But the example you got - pretty much gives you the structure of such use - nothing is missed - everything else is in link you already know - https://cloud.google.com/bigquery/user-defined-functions - and still applicable and the only you need
As of me personally - i've learned about inline js udf relatively long ago from below links (just few of them)
http://www.slideshare.net/BigDataSpain/thomas-park-hands-on-with-big-query-javascript-udfs-bigdataspain-2014
https://www.youtube.com/watch?v=6TYA6hy44Jo
https://www.youtube.com/watch?v=GrD7ymUPt3M (go to 28+ min)

sqlSave error: table not found

I'm trying to save a R dataframe back to a sql database with the following code:
channel <- odbcConnect("db")
sqlSave(db, new_data, '[mydb].[dbo].mytable', fast=T, rownames=F, append=TRUE)
However, this returns the error "table not found on channel", while simultaneously creating an empty table with column names. Rerunning the code returns the error "There is already an object named 'mytable' in the database". This continues in a loop - can someone spot the error?
Is this about what your data set looks like?
MemberNum x t.x T.cal m.x T.star h.x h.m.x e.trans e.spend
1 2.910165e+12 0 0 205 8.77 52 0 0 0.0449161
I've had this exact problem a few times. It has nothing to do with a table not being found on the channel. From my experience, sqlSave has trouble with dates and scientific notation. Try converting x to a factor:
new_data$x = as.factor(new_data$x)
and then sqlSave. If that doesn't work, try as.numeric and even as.character (even though this isn't the format that you want.
As a first shot try to run sqlTables(db) to check the tables in the db and their correct names.
You could then potentially use this functions return values as the input to sqlSave(...)
It seems you are trying to write to a SQL Server. If you specify the database name in the ODBC connection, and then refer to the table as "dbo.mytable" it might help.
I could do it changing the connection in the driver odbc. When you open it, you can do it for one db or in general for all dbs. When you opened it for one db, you will not have a problem with sqlSave().