SAP HANA Procedure Dynamic SQL Select Into Variable: Not Working - sql

Any ideas on how to use spatial functions in either a procedure or a calculation view? I cannot use a table function, as I need a cursor. Please see issues below:
I tried dynamic SQL in a stored procedure with select into (Doesn't allow into):
(About three months back it did work, but now cannot activate?)
This blog says it should work:
https://blogs.sap.com/2017/04/18/sap-hana-2.0-sps-01-new-developer-features-database-development/
Dynamic SQL:
EXECUTE IMMEDIATE 'SELECT NEW ST_Point(' || char(39) || 'POINT(' || decEndPointLong1 || ' ' || decEndPointLat1 || ')' || char(39) || ', 4326).ST_Distance( NEW ST_Point(' || char(39) || 'POINT(' || CURRLONG || ' ' || CURRLAT || ')' || char(39) || ', 4326)) FROM DUMMY' INTO dDistEP1;
Then, I thought that I would create a calculation view,
This blog says it should work:
https://blogs.sap.com/2018/02/23/compute-distance-using-a-calculation-view-xs-advanced-model/
But, does not allow the use of spatial functions in ether columnengine or SQL engine.
Calculated Column:
I went back and tried to re-activate the procedure that contains this code and has been working, and still works, but if I edit it and try to activate it has the same compile error. Cannot select into variable. So, something has changed since I first created this procedure.

​Wow, I stumbled upon an alternate syntax that does not need single quotes:
​
https://blogs.sap.com/2017/02/17/transforming-spatial-data-in-sap-hana/
SELECT NEW ST_Point(-117.0400842, 32.92197086).ST_SRID(4326).ST_Distance( NEW ST_Point(-117.0394467, 32.92241185).ST_SRID(4326)) FROM DUMMY
Now, I think that I can eliminate the Dynamic SQL.
Looking at the two differ ways:
1) SELECT NEW ST_Point(-117.0400842, 32.92197086).ST_SRID(4326).ST_Distance( NEW ST_Point(-117.0394467, 32.92241185).ST_SRID(4326)) FROM DUMMY;
2) SELECT NEW ST_Point('POINT(-117.0400842 32.92197086)', 4326).ST_Distance( NEW ST_Point('POINT(-117.0394467 32.92241185)', 4326)) FROM DUMMY;
They yield slightly different results (meters):
77.06
77.12
Probably, because (1) converts a calculated point to 4326, and (2) calculates the point based on 4326.
So, this code:
EXECUTE IMMEDIATE 'SELECT NEW ST_Point(' || char(39) || 'POINT(' || decEndPointLong1 || ' ' || decEndPointLat1 || ')' || char(39) || ', 4326).ST_Distance( NEW ST_Point(' || char(39) || 'POINT(' || CURRLONG || ' ' || CURRLAT || ')' || char(39) || ', 4326)) FROM DUMMY' INTO dDistEP1;
​Boiled down to:
SELECT r1.FROMLAT INTO decEndPointLat1 FROM DUMMY;
SELECT r1.FROMLONG INTO decEndPointLong1 FROM DUMMY;
SELECT NEW ST_Point(decEndPointLong1, decEndPointLat1).ST_SRID(4326) INTO stEndCoord1 FROM DUMMY;
SELECT NEW ST_Point(CURRLONG, CURRLAT).ST_SRID(4326) INTO stCurrCoord FROM DUMMY;
SELECT stEndCoord1.ST_Distance(stCurrCoord) INTO dDistEP1 FROM DUMMY;

Related

Not properly closed sql command

I have this code:
def_where:=def_where||' TO_CHAR(date_of_input,''MM'') like '''||'to_char(date_of_input,''MM'')=nvl(:DSP_month,to_char(date_of_input,''MM''))'||'%' ||'to_char(date_of_input,''RRRR'')=nvl(:DSP_year,to_char(date_of_input,''RRRR''))'||'%''';
and i m getting error sql command not properly ended.
def_where suggest, that this is part of dynamically built query, condition of where clause. But produced string makes no sense, it should be something like:
declare
def_where varchar2(32767) := '';
begin
def_where := def_where
|| ' to_char(date_of_input, ''MM'') '
|| ' = nvl(:DSP_month, to_char(date_of_input, ''MM'')) and'
|| ' to_char(date_of_input, ''RRRR'') '
|| ' = nvl(:DSP_year, to_char(date_of_input, ''RRRR''))';
dbms_output.put_line(def_where);
end;
Look what you got from dbms_output, correct this syntax if needed. You could also rewrite your string to get this:
(extract(month from date_of_input) = :DSP_month or :DSP_month is null) and
(extract(year from date_of_input) = :DSP_year or :DSP_year is null)

Oracle SQL: Using CHR() function with || concatenate and join

Query below returns error
SELECT 'mailto:'|| fscp.parameter_value || '?subject=' || wfn.subject nid_subject || chr(38)
FROM apps.wf_notifications wfn, apps.fnd_svc_comp_param_vals_v fscp
WHERE fscp.component_id = :component_id
AND component_parameter_id = :param
AND wfn.item_key = :itemkey;
Error
ORA-00923: FROM keyword not found where expected
00923.00000 - "FROM keyword not found where expected"
When I remove the '|| chr(38)' at the end of the select statement, the query runs fine.
Something related to joining tables? Because the below query also works fine:
select 'Text: '||chr(39)||wfn.notification_id||chr(39) from wf_notifications wfn;
You have this in the select:
|| wfn.subject nid_subject ||
Perhaps you intend:
SELECT 'mailto:'|| fscp.parameter_value || '?subject=' || wfn.subject || nid_subject || chr(38)
----------------------------------------------------------------------^
Alex is right. The key in the question is that it works without chr(38). So, try this:
SELECT ('mailto:'|| fscp.parameter_value || '?subject=' || wfn.subject || chr(38) ) as nid_subject
Notice the use of parentheses and as to make it clear that a column alias is being defined.

Error in dynamic SQL query. Missing expression with correct syntax

I have a problem working with a stored procedure on work.
It's a stored procedure which is used by several bigger procedures. The procedure which does the work is called C, and the ones who call it are A and B.
The problem I have is that when I run A, everything goes smoothly, but when I run B, I get a missing expression error, which I don't get when I call A, even tough B and A have the same flow of procedure calls (so, it's kind of a really weird error).
The C procedure has the same code:
procedure C ( LO in varchar2,
EN in varchar2,
CA in array1d,
IA in number,
AR in array2d )
is
CQ varchar2(5);
ET varchar2(2000);
OL varchar2(100);
NE varchar2(100);
TE varchar2(100);
XU varchar2(100);
begin
LO := '05';
TE := 'VAR';
CQ := '''';
OL := CQ || LO || CQ;
TE := CQ || TE || CQ;
NE := CQ || EN || CQ;
ET := 'PAR1 = ' || CA(1) || ',' ||
'PAR2 = ' || CA(2) || ',' ||
'PAR3 = ' || CA(3) || ',' ||
'PAR4 = ' || CA(4) || ',' ||
'PAR5 = ' || CA(5) || ',' ||
'PAR6 = ' || CA(6) || ',' ||
'PAR7 = ' || CA(7) || ',' ||
'PAR8 = ' || CA(8) || ',' ||
'PAR9 = ' || CA(9);
execute immediate 'update table_st set ' || ET || '
where field1 = ' || OL || '
AND field2 = ' || NE || '
AND field3 = ' || TE;
end;
The error I get is missing expression, and it seems to appear on the first line of the execute immediate. After some analysis, I realized the data from the 2d ARRAY is initialized with some empty strings ''.
I am wondering if you could help me to see this error from a new perspective, because as I see it, there seems to be no syntax error to justify the missing expression error I get, but I know I may be wrong.
If further details are needed, let me know.
At a minimum, I'd say the variables LO, CQ haven't been declared, and EN and CA haven't been declared or initialized.
Also, you declared NE as a verchar2 when I think you meant varchar2.
I also agree with Juan's observation that you may want to double check this line:
CQ := q'[']';
Did you mean:
CQ := q'['']';
Honestly not sure, but worth a look.
Oracle should tell you if the procedure compiles, and I think these errors alone will prevent it from doing that. If you don't ever declare the contents of EN and CA, it might still compile but fail when it runs.

ORA-00933 Error for to_char formatting PLSQL

I have the following codes:
IF nvl(p_value, 0) >= 0 THEN
l_currency_prefix := 'scc.currency_prefix_pos';
l_currency_suffix := 'scc.currency_suffix_pos';
ELSE
l_currency_prefix := 'scc.currency_prefix_neg';
l_currency_suffix := 'scc.currency_suffix_neg';
END IF;
l_query := 'SELECT nvl('||l_currency_prefix||', '')'
||'trim(to_char('||p_value||
',scc.currency_format
,'||'NLS_NUMERIC_CHARACTERS=' || 'scc.decimal_group_separator'||'))'
||'nvl('||l_currency_suffix||', '')
FROM gss.gss_currency_locale scc
WHERE scc.country_code =' ||p_country_code||
'AND scc.currency_code ='|| p_currency_code||
'AND rownum=1';
and here is the dbms output for l_query:
SELECT nvl(scc.currency_prefix_pos, ')trim(to_char(10000,scc.currency_format
,NLS_NUMERIC_CHARACTERS=scc.decimal_group_separator))nvl(scc.currency_suffix_pos, ')
FROM gss.gss_currency_locale scc
WHERE scc.country_code =USAND scc.currency_code =USDAND rownum=1
However, it keep showing an ORA-00933 errors.
I debug these piece of code for few hours and could not find where is the errors.
Could some one please provide some advice on this?
Now some of the problems are obvious. You need something like this:
l_query := 'SELECT nvl('||l_currency_prefix||',
||'trim(to_char('||p_value||
',scc.currency_format || ')' ||
FROM gss.gss_currency_locale scc
WHERE scc.country_code = ''' ||p_country_code|| '''' ||
' AND scc.currency_code = '''|| p_currency_code|| '''' ||
' AND rownum=1';
(I'm not sure if that is 100 percent correct.)
Usually, when creating queries this way, I use replace() instead of direct substitution. Something like:
l_query := 'select nvl(#currency_prefix, trim(#p_value, #currency_format))
from . . . ';
l_query := replace(l_query, '#currency_prefix', l_currency_prefix);
l_query := replace(l_query, '#p_value', p_value);
. . .
I find that this approach makes it much easier to maintain the code and to see what it is doing.

Correctly inserting literals in PL/PgSQL EXECUTE dynamic queries

The following is part of a plpgsql function. The problem is that the result of source_geom and target_geom is a character varying data type, and therefore I need to surround the both source_geom and target_geom in quotes(' '). The thing is that in plpgsql language how I don't know I can do it.
Here's what I have at the moment:
EXECUTE 'update ' || quote_ident(geom_table) ||
' SET source = ' || source_geom ||
', target = ' || target_geom ||
' WHERE ' || quote_ident(gid_cname) || ' = ' || _r.id;
The error that I am having is the following;
ERROR: syntax error at or near "C03B9E3B66052D400DDEFC2BD0F24140"
LINE 1: ...pdate track_points SET source = 0101000020E6100000C03B9E3B66...
^
QUERY: update track_points SET source = 0101000020E6100000C03B9E3B66052D400DDEFC2BD0F24140, target = 0101000020E610000075690DEF83052D40F88E75CCD4F24140 WHERE ogc_fid = 2
CONTEXT: PL/pgSQL function "create_network" line 26 at EXECUTE statement
Please any suggestions how I can solve this problem.?
Using EXECUTE ... USING with the format() function and its format specifiers will make your code much safer, simpler, easier to read and probably faster.
SQL INJECTION WARNING: If you ever accept source_geom or target_geom from the end user, your code is potentially vulnerable to SQL injection. It is important to use parameterized statements (like EXECUTE ... USING) or failing that, paranoid quoting to prevent SQL injection attacks. Even if you don't think your function takes user input you should still harden it against SQL injection, because you don't know how your app will evolve.
If you're on a newer PostgreSQL with the format function your code can be significantly simplified into:
EXECUTE format('update %I SET source = %L, target = %L WHERE %I = %L',
geom_table, source_geom, target_geom, gid_cname, _r.id);
... which handles identifier (%I) and literal (%L) quoting for you using format specifiers so you don't have to write all that awful || concatenation and quote_literal/quote_ident stuff.
Then, as per the documentation on EXECUTE ... USING you can further refine the query into:
EXECUTE format(
'update %I SET source = $1, target = $2 WHERE %I = $3',
geom_table, gid_cname
) USING source_geom, target_geom, _r.id;
which turns the query into a parameterised statement, clearly separating parameters from identifiers and reducing string processing costs for a more efficient query.
Use extra quotes:
EXECUTE 'update ' || quote_ident(geom_table) ||
' SET source = ''' || source_geom || '''
, target = ''' || target_geom || '''
WHERE ' || quote_ident(gid_cname) || ' = ' || _r.id;