Greenplum 4.3 doesn't support this 'USING' grammar - greenplum

EXECUTE 'INSERT INTO ' || tablename_2 || ' VALUES (($1).*)' USING NEW ;
Greenplum (based on Postgres 8.2) doesn't support this 'using' grammar, how to do this operator in Greenplum 4.3
Error info:
ERROR: syntax error at or near "USING" LINE 1: ...LECT 'INSERT INTO
' || $1 ||' VALUES (($1).)' USING $2
^ QUERY: SELECT 'INSERT INTO ' || $1 ||' VALUES (($1).)' USING $2
CONTEXT: SQL statement in PL/PgSQL function "dp_insert_trigger" near
line 13

Dynamic SQL in Greenplum requires the entire SQL statement to be created and it doesn't support "using new".
v_sql := 'insert into ' || p_target_table_name || ' (col1, col2, col3) ' ||
'select col1, col2, col3 from ' || p_source_table_name;
execute v_sql;
Singleton insert statements should be avoided in Greenplum because it is so very slow. Instead, do bulk operations. This lack of a feature has never come up because inserting into a table row by row is so heavily discouraged that this feature isn't needed.

The USING clause for dynamic commands was introduced in version 8.4. In 8.2 you have to assemble the string with all of its dynamic parts using string concatenation and the quote_literal(), quote_identifier() and quote_nullable() functions.
PG 8.2 is unsupported since December 2011 and even the respectable 8.4 is beyond its lifetime for more than 18 months now. You should really upgrade.

Related

Oracle: Dynamic SQL with Update not working

I have this instruction
UPDATE TABLE1
SET INC =
(select INC from TABLE2
WHERE KEY = 'KEY_VALUE1'
FETCH FIRST 1 ROW ONLY);
This working fine if i run from sqlPlus or if I use in PLSQL but, if I using in Dynamic SQL, not working
sqlStmt:= 'UPDATE TABLE1'
|| 'SET INC = '
|| '(select INC from TABLE2 '
|| 'WHERE KEY = ''' || v_key_value || ''' '
|| 'FETCH FIRST 1 ROW ONLY); ';
BEGIN
EXECUTE IMMEDIATE sqlStmt;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('{"errorcode":"' || SQLERRM);
ROLLBACK;
END;
This instruction return this error:
{"errorcode":"ORA-00933: comando SQL terminato erroneamente
Someone can you help me?
Regards,
Marco
You don't want to have a semicolon at the end of the string you are building and passing to execute immediate.
It's not the cause of your error. But it would be much kinder to the database to write this using bind variables rather than concatenating literals. Of course, since there is no reason to be using dynamic SQL for this sort of update statement, I'm guessing your actual use case is different and that you are actually using bind variables and/or there is actually a reason why bind variables aren't an option.

SQL Error: ORA-00904: "CNPPARMID": invalid identifier

I have a function:
At line execute immediate 'select ' || schemaname || '.' || value1 || '_seq.nextval from dual' into cnpParmId;
Am getting error as SQL Error: ORA-00904: "CNPPARMID": invalid identifier.
I tried to put the cnpParmId inside the quotes, tried into cnpParmId from dual, in all possible ways. But its not working.
Please give me some ideas to solve this issue.
Thanks!!
Your function compiles successfully, and you get the error at runtime:
select test(user, 'T42') from dual;
SQL Error: ORA-00904: "CNPPARMID": invalid identifier
ORA-06512: at "MYSCHEMA.TEST", line 23
You said the error was on the first execute immediate, but that is line 21 not line 23, and if it was that cnpParmId reference it was complaining about then it would cause a compilation error - the function would be created but with errors/warnings, and it wouldn't be possible to call it.
So it's the second execute immediate, at line 23, which is erroring at runtime (reformatted slightly):
execute immediate
'select ''T'' from dual where cnpParmId not in ' ||
'(select value1 from ' || schemaname || '.' || tablename || ')'
into good;
As GolezTrol said, the dynamic statement is executed in a SQL context that has no visibility of any of your PL/SQL variables. It's the same as running the generated statement:
select 'T' from dual where cnpParmId not in (select value1 from myschema.t42);
... directly in SQL*Plus or SQL Developer, which also gets:
SQL Error: ORA-00904: "CNPPARMID": invalid identifier
00904. 00000 - "%s: invalid identifier"
As a variation of GolezTrol's concatenation, you could use a bind variable to prevent hard-parsing each time round your loop, but you also need to provide your primary key column name as value1 also won't be recognised; and that has to be concatenated in:
execute immediate
'select ''T'' from dual where :cnpParmId not in ' ||
'(select ' || value1 || ' from ' || schemaname || '.' || tablename || ')'
into good using cnpParmId;
which compiles and runs.
You could also use not exists rather than not in, which might perform better since you're looking for the (indexed) primary key:
execute immediate
'select ''T'' from dual where not exists (select null from '
|| schemaname || '.' || tablename || ' where ' || value1 || ' = :cnpParmId)'
into good using cnpParmId;
You can also move the query that finds value1 outside the loop; there's no benefit to calling that repeatedly.
It looks like you're doing this because you have primary key values that weren't generated from the sequence. If you're still adding new records like that - e.g. via a trigger that only uses the sequence if the passed key column is null - then you need a hack like this or an insert loop that catches the ORA-01001. But this approach still has a race condition - another session can simultaneously do a manual insert with the same value your function finds, and one of the sessions will get an error.
It would usually be better to only use the sequence; if you are now doing that, or can change to do that, then a one-off adjustment of all your sequences to be higher than the current maximum key value would be simpler.
Using execute immediate, you execute the statement outside of the scope of the function, so it can't use the PLSQL variable. I'd solve this by executing it as a normal query and use SELECT INTO or a cursor to fetch the query result.
But it should also work if you simply substitute the value into the query string yourself, like this:
Change
'select ''T'' from dual where cnpParmId not in ' ||
into
'select ''T'' from dual where ' || cnpParmId || ' not in ' ||

sql command not properly ended for select statement

I have a pl/sql function and in that i have the following piece of code:
execute immediate 'select ' || schemaname || '.' || value1 || '_seq.nextval from dual into cnpParmId';
for this line, I am getting an error:
SQL Error: ORA-00933: SQL command not properly ended
In the above code I am getting the value1 from the result of a select query. schemaname is the input of the function and cnpParmId is the return value of the function.
I tried different ways to solve this but I still get the error.
It's hard to say without showing us more of your procedure, but I think it's a fair guess that you didn't mean to concatenate cnpParmId in your dynamic SQL (how could the dynamic SQL possibly know how to interpret cnpParmId?). cnpParmId is probably defined somewhere in your procedure.
Instead, you probably meant to use the into clause of the execute immediate command:
execute immediate 'select ' || schemaname || '.' || value1 || '_seq.nextval from dual'
into cnpParmId;

ORACLE: Cursor with dynamic query - throws error "invalid identifier" for cursor field

I have a logic to implement where I have to use dynamic sql(column names and where clause is decided on the fly).So here my cursor(emp_ref_cursor) has a dynamic sql, and has 3 cursor fields(emp_id,emp_name,dept).
Using these cursor fields in WHERE clause I am trying to execute another dynamic sql inside the loop.Bt oracle isn't able to identify the cursor field and throws an error like "ORA-00904: "EMP_REC"."EMP_ID": invalid identifier" though I am able to output emp_rec.emp_id through DBMS_OUTPUT.
NOTE: Please don't comment on the code quality this is not the actual code.
This is just used to describe the problem. I can't post the actual code due to
some compliance related stuff.
DECLARE
emp_ref_cursor sys_refcursor;
v_sql varchar2(3900);
TYPE emp_rec_type IS RECORD (emp_id number,emp_name varchar2(100),dept_id varchar2(100));
emp_rec emp_rec_type;
v_dept_id number:='1234';
v_dob varchar2(100);
v_desig varchar2(100);
x_dynamic_col_1 varchar2(100):='dob'; --dynamic column(based on some condition)
x_dynamic_col_2 varchar2(100):='designation'; --dynamic column(based on some condition)
x_dynamic_col_3 varchar2(100):='emp_id'; --dynamic column(based on some condition)
BEGIN
v_sql:='SELECT emp_id,emp_name,dept FROM employee WHERE dept_id=' || v_dept_id;
OPEN emp_ref_cursor FOR v_sql;
LOOP
FETCH emp_ref_cursor INTO emp_rec;
exit WHEN emp_ref_cursor%NOTFOUND;
stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
FROM employee A
WHERE emp_id=emp_rec.' || x_dynamic_col_3;
DBMS_OUTPUT.PUT_LINE(stmt);
--Prints the SQL query as expected
DBMS_OUTPUT.PUT_LINE('emp_rec.emp_id:'||emp_rec.emp_id);
--Displays the value!!!
execute immediate stmt into v_dob, v_desig;
--But why is it saying emp_rec.emp_id is invalid identifier??
END LOOP;
END;
You have emp_rec defined as a local PL/SQL variable. None of the PL/SQL data is in scope to the dynamic SQL execution. When it is executed it as if you tried to run the statement - as it is displayed by your dbms_output standalone in a separate SQL context. If you did that it would be clear that emp_rec doesn't exist to the query.
You refer to it you would need to use a bind variable:
WHERE emp_id=:dynamic_col_3';
And then execute it with:
execute immediate stmt using emp_rec.emp_id;
But you can't use the x_dynamic_col_3 local variable in the using clause. Since - in this example anyway - the query would also need to change to use a different table column is the dynamic record field changed - that doesn't seem too much of a problem. But you said the where clause will change on the fly too. In that case you could have another local variable that you set to the relevant x field before the executin.
You have incorrect using of EXECUTE IMMEDIATE. You don't need to put INTO clause to SQL query. Use this instead:
stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
FROM employee A
WHERE emp_id=emp_rec.' || x_dynamic_col_3;
execute immediate stmt into v_dob, v_desig;

Replace character in all columns using Oracle Data Modeler

Is it possible to simply change character in name of tables columns? At the moment columns have seperator - and I want to change it with underscore (_) . Is it possible to do it easy with 1 click or should I go through all tables and change it by hand?
I don't know oracle SQL data modeler. If you have access to SQL*Plus or another developer tool, you can run script, it will change all columns of tables in your schema:
begin
for i in (select table_name, column_name from user_tab_columns) loop
if instr(i.column_name, 'A') > 0 then
execute immediate 'alter table ' || i.table_name || ' rename column ' ||
i.column_name || ' to ' || replace(i.column, 'A', 'B');
end if;
end loop;
end;
/
Here 'A' is symbol that you want to replace and 'B' - new symbol to use. But be careful, such scripts can be dangerous. Try it on test schema first.

Resources