Alter sequence .nextval in Oracle SQL 11 with prepared statement - sql

I'm trying to advance a sequence by a negative number but I keep getting the following error:
ORA-02286: no options specified for ALTER SEQUENCE
So far no amount of Googling has helped. The statement that I use is
ALTER SEQUENCE %s.nextval INCREMENT BY ?
The sequence name is generally schema.table_name_seq. Including the schema name is unavoidable because the connection is not necessarily to the same one.
Appending an inconsequential option like minvalue 1 did nothing to satisfy it either.
My second attempt was to drop .nextval from the query and run ALTER directly on the sequence (just throwing stuff at the wall to see what sticks at this point), ie:
ALTER SEQUENCE %s INCREMENT BY ?
which results in
ORA-01722: invalid number
Next I supplied a positive integer and negated it in the query (INCREMENT BY -?) which produced the same error. The query is prepared as such:
num = -1 * Math.abs(num);
stmt = conn.prepareStatement(sql);
stmt.setLong(1, num); //also tried setInt()
stmt.execute();
The idea is to set the .nextval sequence for a given table back to an arbitrary number (but always more than minval).

JustinCave's comment was most illuminating:
alter sequence is DDL. You cannot use bind variables in DDL. You would need to dynamically build the DDL statement you want and execute that and it wouldn't make sense to use a PreparedStatement to do so.
Recognizing that there are better ways to do it, but acknowledging time constraints, I constructed the following SQL statement:
ALTER SEQUENCE %s INCREMENT BY %d
which works like a charm. Yes, the number to advance by is hardcoded in each request. Not the best solution but I cannot create stored procedures at this point, so it'll have to do.
Thank you Justin.

Related

Token unkown error in stored procedure when updating on external database

create or alter procedure UPDATECAS (
VNEWSTOCK double precision,
as
declare variable LCCOMANDO2 varchar(256);
begin
LCCOMANDO2 = 'update CAS
set STOCK = STOCK-' || :VNEWSTOCK || '';
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey'
suspend;
end
I am using Firebird and I want to create a stored procedure to do an update in another database and I do not understand what I am missing because when compiling it gives me the following error:
can't format message 13:896 -- message file C:\WINDOWS\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Token unknown.
suspend
The error code 13:896 is usually shown as error code 336397184, which translates to message "Invalid token". (as an aside: The "can't format message" error is an indication that you're using a fbclient.dll that can't find the firebird.msg file with error messages, or you're using an older version that doesn't contain the specific message)
In this specific case, the problem is that you made a syntax error: your statement is missing the word DO, as shown in FOR EXECUTE STATEMENT in the Firebird 2.5 Language Reference. As a result, the Firebird parser finds a SUSPEND in a position it doesn't expect it (it either expects DO, or another token from the FOR EXECUTE STATEMENT syntax). The - obvious, but incorrect - fix would be:
for execute statement LCCOMANDO2 on external 'C:\DB\DB.GDB' as
user 'SYSDBA' password 'masterkey' do
begin
suspend;
end
Note: enclosing the suspend; in begin ... end is not necessary, but in my opinion it improves readability.
This would solve the immediate problem, but will then result in another error, because the FOR EXECUTE STATEMENT is intended to execute statements that produce a result set, and UPDATE does not produce a result set.
Instead, you need to use EXECUTE STATEMENT without FOR. I would also highly recommend that you appropriately parameterize your update statement, instead of concatenating values into the query string. Given your stored procedure doesn't produce any data (it has no RETURNS clause), use of the SUSPEND clause is also inappropriate.
The final code should be something like:
create or alter procedure UPDATECAS (VNEWSTOCK double precision)
as
begin
execute statement ('update CAS set STOCK = STOCK - :newstock') (newstock = VNEWSTOCK)
on external 'C:\DB\DB.GDB' as user 'SYSDBA' password 'masterkey';
end
Be aware though, that using double precision for something that is stock doesn't seem appropriate. Usually stock is discrete units, so INTEGER or BIGINT would be more appropriate, or if you need decimal values, the exactness of DECIMAL (or NUMERIC) is probably better than the inexactness of DOUBLE PRECISION.

DB2 stored procedure gave syntax errors

I am creating a stored procedure for db2. But it is giving an error saying that
"SQL Error [42601]: An unexpected token "END-OF-STATEMENT" was found
following "SS_TOKEN_BAK". Expected tokens may include: " END IF"..
SQLCODE=-104, SQLSTATE=42601, DRIVER=4.23.42".
Following is my stored procedure.
CREATE OR REPLACE PROCEDURE TOKEN_CLEANUP_SP
BEGIN
DECLARE batchSize INTEGER;
-- ------------------------------------------
-- CONFIGURABLE ATTRIBUTES
-- ------------------------------------------
SET batchSize = 10000; -- SET BATCH SIZE FOR AVOID TABLE LOCKS [DEFAULT : 10000]
-- ------------------------------------------------------
-- BACKUP IDN_OAUTH2_ACCESS_TOKEN TABLE
-- ------------------------------------------------------
IF EXISTS (SELECT TABLE_NAME FROM TABLES WHERE TABLE_NAME = 'IDN_OAUTH2_ACCESS_TOKEN_BAK')
THEN
DROP TABLE IDN_OAUTH2_ACCESS_TOKEN_BAK;
END IF;
END/
Is anyone face this type of issue. Any help on this would be much appreciated.
Verify that you have the end-of-statement delimiter configured correctly for whatever tool submits the 'CREATE OR REPLACE' procedure. Different tools have different ways to configure the block terminator (alternatively known end of statement delimiter). For command line scripts, use --#SET TERMINATOR / at the start of the file, other ways are possible.
Your code sample shows / as the block terminator, so you might want to use that character as the block delimiter. The semi-colon terminates statements inside the block.
Separately you should see that your code won't compile if the specified table does not exist in the implied schema at compilation time, because you are using static SQL. You may want to use dynamic SQL instead for the drop table statement (search for 'EXECUTE IMMEDIATE' examples).

Error in creating 2 tables in Green Screen STRSQL

I'm getting an error while trying to create 2 tables in Green Screen STRSQL.
CREATE TABLE QTEMP/CUSTOMER AS (SELECT * FROM CBHHUBFP/SSCUSTP)
CREATE TABLE QTEMP/ADDRESS AS (SELECT * FROM QTEMP/CUSTOMER)
ERROR: Keyword Create not expected
Valied Tokens End-Of-Statement
Am I missing something here?
Using STRSQL you can only execute one SQL statement at time.
Re my comment to the accepted answer by #dcieslak, the following is an example of a Dynamic Compound Statement (DCS) with syntax that should be valid for use with the /*SYS naming-option, on any system [level of DB2 for IBM i], since the availability of that DCS feature; notice the addition of the WITH DATA clause to make the statement syntactically correct, and enclosing the two semicolon separated requests as CREATE TABLE statements, inside of the BEGIN and END:
begin
CREATE TABLE QTEMP/CUSTOMER AS (SELECT * FROM qiws/qcustcdt )
with data
;
CREATE TABLE QTEMP/ADDRESS AS (SELECT * FROM QTEMP/CUSTOMER)
with data
;
end
-- Table ADDRESS created in QTEMP. /* <-- feedback of final rqs */
While that is possible to enter as a single request, there is likely no point in coding that, per the extra overhead; perhaps if run under isolation and doing more work and coding exception handling, then there would be value. IOW, the Start Interactive SQL Session (STRSQL) scripting environment allows the isolation and user decisions to react to exceptions when the statement are entered individually, successively, Enter pressed after each.
So unless the idea is to test what might be written in a routine [as a compound statement, statements between BEGIN-END pairs] without actually coding the CREATE PROCEDURE [or CREATE FUNCTION ¿or CREATE TRIGGER?] with a routine-body, then the implicitly created routine [as procedure] that is then run and deleted to implement the DCS, is probably mostly just a bunch of extra/unnecessary work.

Oracle SQL*Plus Variable Declaration

I can't for the life of me find out to get the behavior I want:
old:insert into build_pc
values (&&buildA, 35,40,32,29,26,22,22,null,13,11,7,1,999)
new:insert into build_pc
values (build_id_seq.nextval, 35,40,32,29,26,22,22,null,13,11,7,1,999)
1 rows inserted.
As part of an SQL transaction I'm trying to save a variable, moreover an integer ID number, so that it can be entered in a few places across the transaction. The problem is SQLDev is being too clever and converting back to he nextval function each time instead of just storing an int.
Google says use set, but that throws this:
SQLPLUS Command Skipped: set buildA = build_id_seq.nextval
As I understand, you want to use a bind variable in SQL Plus. Please, try this:
variable buildA NUMBER;
exec select build_id_seq.nextval into :buildA from dual;
insert into build_pc values (:buildA, 35,40,32,29,26,22,22,null,13,11,7,1,999);
If you use 11g you do not need to SELECT the value of sequence, you can use:
variable buildA NUMBER;
exec :buildA := build_id_seq.nextval;
insert into build_pc values (:buildA, 35,40,32,29,26,22,22,null,13,11,7,1,999);
Hope this helps!
You should be using define rather than set for a substitution variable:
define buildA = build_id_seq.nextval
... but it will be substituted verbatim wherever you reference &buildA, incrementing the sequence each time.
You could use a bind variable or the new_value syntax, but you probably just want to refer to build_id_seq.nextval the first time you use it, and build_id_seq.currval on all the subsequent references, rather than trying to store it yourself.
As the documentation says:
CURRVAL: Returns the current value of a sequence
NEXTVAL: Increments the sequence and returns the next value
So when you call nextval the sequence is incremented, and subsequent calls to currval in the same session get the same value, without incrementing again.
This is useful for creating parent/child records, for example, where you use nextval to create the primary key value and then currval to use the same value as a foreign key in child records.

Informix SQL update command error 746

I tried to update the field "contract_id" in the table "contract_scan_image".
However, the update was failed and an error "746: Field contract_id and type of contract_scan_image cannot be updated!" was shown.
My SQL command is:
update contract_scan_image
set contract_id = '14864730'
where contract_id = '1486473'
and type = 'RM'
and account = '00193400944'
Does anyone know what happened and how to fix it?
Error message -746 is for user-defined errors. It typically is used in stored procedures in a RAISE EXCEPTION statement:
RAISE EXCEPTION -746, 0, "Field contract_id and type of contract_scan_image cannot be updated!"
The actual message text for error -746 in the message files is:
%s
That is, it prints the string it is given as a string.
So, you are going to need to track down the triggers and stored procedures invoked by those triggers on the contract_scan_image table, and deduce from where the error is generated what you are doing wrong. Superficially, though, it appears that you are not allowed to alter the contract ID, yet that is what you are trying to do.
First things first, I would take a look at a list of Reserved words in SQL - https://drupal.org/node/141051
I would get in the habit of surrounding fields with `` See below:
update contract_scan_image
set `contract_id` = '14864730'
where `contract_id` = '1486473'
and `type` = 'RM'
and `account` = '00193400944'
** Note - type is a reserved word
The error is caused by something being triggered. Then no table can be modified by UPDATE command.
Finally I deleted the record I want to update. Then added back the modified record.
I copy the error description here from the net for reference.
BTW, I asked my supervisor and he said he did trigger something to cause this. (He didn't tell me how to un-trigger it...)
-746
THE SQL STATEMENT IN FUNCTION, TRIGGER, OR IN STORED PROCEDURE name VIOLATES THE NESTING SQL RESTRICTION
Explanation
If a table is being modified (by INSERT, DELETE, UPDATE, or MERGE), the table can not be accessed by the lower level nesting SQL statement.
If any table is being accessed by a SELECT statement, no table can be modified (by INSERT, DELETE, UPDATE, or MERGE) in any lower level nesting SQL statement.
System action
The SELECT, INSERT, DELETE, UPDATE or MERGE SQL statement failed.
Programmer response
Remove the failing statement from the named function, trigger or the stored procedure.
SQLSTATE
57053