I am using a barcode scanner to scan in barcodes (that consist of the order^location - I use the ^ as a separator) which i then need to separate and put the two values into two text fields. The idea is to scan the barcode into a third text field and then its separated using a process after save is pressed - These are then saved into separate table columns. I have the below which separates the text but I am now trying to get the values held in the array into the text fields on the APEX form.
I have the below code which works in SQL developer with the following lines however when i changed them to try put the value into a text field it fails. I wondered whether i have it correct or maybe incorrect syntax?
dbms_output.put_line(v_array(1)); -- This works in SQL Developer
:P1_ORDER := dbms_output.put_line(v_array(1)); -- Fails in SQL Developer & APEX
I get the following when i attempt to run the below in SQL developer. Please can someone help me pass the values in my array to the text fields on my APEX Form. Thanks.
ORA-06550: line 17, column 13:
PLS-00222: no function with name 'PUT_LINE' exists in this scope
ORA-06550: line 17, column 5:
PL/SQL: Statement ignored
declare
v_array apex_application_global.vc_arr2;
P1_ORDER number;
P1_LOCATION number;
begin
-- Convert delimited string to array
v_array := apex_util.string_to_table(:P1_JOB_NUMBER,'^');
--dbms_output.put_line(v_array(1));
--dbms_output.put_line(v_array(2));
:P1_ORDER := dbms_output.put_line(v_array(1));
:P1_LOCATION := dbms_output.put_line(v_array(2));
end;
See put_line is not a function ,its a procedure in dbms_output package .
You can't assign dbms_output.put_line to any variable .
Try this
declare
v_array apex_application_global.vc_arr2;
P1_ORDER number;
P1_LOCATION number;
begin
-- Convert delimited string to array
v_array := apex_util.string_to_table(:P1_JOB_NUMBER,'^');
--dbms_output.put_line(v_array(1));
--dbms_output.put_line(v_array(2));
P1_ORDER := v_array(1);
P1_LOCATION := v_array(2);
end;
Related
I want to leave some fields empty (i.e. Null) when I insert values into table. I don't see why would I want to have a DB full of empty strings in fields.
I use Delphi 10, FireDAC and local SQLite DB.
Edit: Provided code is just an example. In my application values are provided by user input and functions, any many of them are optional. If value is empty, I would like to keep it at Null or default value. Creating multiple variants of ExecSQL and nesting If statements isn't an option too - there are too many optional fields (18, to be exact).
Test table:
CREATE TABLE "Clients" (
"Name" TEXT,
"Notes" TEXT
);
This is how I tried it:
var someName,someNote: string;
begin
{...}
someName:='Vasya';
someNote:='';
FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name,Notes) VALUES (:nameval,:notesval)',
[someName, IfThen(someNote.isEmpty, Null, somenote)]);
This raises an exception:
could not convert variant of type (Null) into type (OleStr)
I've tried to overload it and specify [ftString,ftString] and it didn't help.
Currently I have to do it like this and I hate this messy code:
FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name,Notes) VALUES ('+
IfThen(someName.isEmpty,'NULL','"'+Sanitize(someName)+'"')+','+
IfThen(someNote.isEmpty,'NULL','"'+Sanitize(someNote)+'"')+');');
Any recommendations?
Edit2: Currently I see an option of creating new row with "INSERT OR REPLACE" and then use multiple UPDATEs in a row for each non-empty value. But this looks direly ineffective. Like this:
FDConnection1.ExecSQL('INSERT OR REPLACE INTO Clients(Name) VALUES (:nameval)',[SomeName]);
id := FDConnection1.ExecSQLScalar('SELECT FROM Clients VALUES id WHERE Name=:nameval',[SomeName]);
if not SomeString.isEmpty then
FDConnection1.ExecSQL('UPDATE Clients SET Notes=:noteval WHERE id=:idval)',[SomeNote,id]);
According to Embarcadero documentation ( here ):
To set the parameter value to Null, specify the parameter data type,
then call the Clear method:
with FDQuery1.ParamByName('name') do begin
DataType := ftString;
Clear;
end;
FDQuery1.ExecSQL;
So, you have to use FDQuery to insert Null values, I suppose. Something like this:
//Assign FDConnection1 to FDQuery1's Connection property
FDQuery1.SQL.Text := 'INSERT OR REPLACE INTO Clients(Name,Notes) VALUES (:nameval,:notesval)';
with FDQuery1.ParamByName('nameval') do
begin
DataType := ftString;
Value := someName;
end;
with FDQuery1.ParamByName('notesval') do
begin
DataType := ftString;
if someNote.IsEmpty then
Clear;
else
Value := someNote;
end;
if not FDConnection1.Connected then
FDConnection.Open;
FDQuery1.ExecSql;
It's not very good idea to execute query as String without parameters because this code is vulnerable to SQL injections.
Some sources tells that it's not enough and you should do something like this:
with FDQuery1.ParamByName('name') do begin
DataType := ftString;
AsString := '';
Clear;
end;
FDQuery1.ExecSQL;
but I can't confirm it. You can try it if main example won't work.
I am trying to create a user generated sequence. According to usual syntax of oracle sequence we can start with a number and increment a value.
Is there a method to write a plsql block (declare begin end) inside a sequence and generate my own sequnce.
example : ABC001
When i call the next val of sequence , the value should be ABC002
PLEASE CLEAR FIRST WHAT YOU EXACTLY WANT TO ASK.
If you are asking HOW TO DYNAMICALLY CREATE SEQUENCE USING PL/SQL, then check below.
Simplest way.
DECLARE
SQL_S VARCHAR2(100);
BEGIN
SQL_S := 'CREATE SEQUENCE SQN_NAME INCREMENT BY 1 START WITH 1';
EXECUTE IMMEDIATE SQL_S;
END;
/
If you want to dynamically create sequence with some DYNAMIC name as argument passed to procedure, then it will be like
CREATE OR REPLACE PROCEDURE DYNAMIC_SQN (ARG IN VARCHAR2) IS
SQL_S VARCHAR2(100);
PARAM1 VARCHAR2(20);
BEGIN
PARAM1 := 'SQN_NAME_' || ARG;
SQL_S := 'CREATE SEQUENCE ' || PARAM1 || ' INCREMENT BY 1 START WITH 1';
EXECUTE IMMEDIATE SQL_S;
END;
/
And if you simply want to insert in to any column, and create the PK using it in addition to some String, then
INSERT INTO TABLE_T VALUES('ABC'|| SEQUENCE_NAME.nextval, OTHER_VALUES);
It will still give you values like : ABC1, ABC2, .... ABC12, ABC13, .... ABC99, ABC100 and so on...
Considering the sample example you have given i m writing the following code
create your sequence, then
insert into seq values('ABC'||YOURSEQUENCENAME.nextval,YOUR_VALUE);
I am using this anonymous function to test a programming construct for inclusion in a larger script:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
INSERT INTO g_to VALUES ('myaddy#internet.com');
END;
But, when I run it, I get:
*Error starting at line : 1 in command -
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
INSERT INTO g_to VALUES ('myaddy#internet.com');
END;
Error report -
ORA-06550: line 10, column 17:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 10, column 5:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:*
Now, the array is clearly defined, so why is the INSERT failing?
When you place the array into a place where it needs to be interpreted by the SQL interpreter (as opposed to the PL/SQL interpreter), then the array must be a database object, rather than locally defined. This is the case when you want to select from an array, for instance.
However, in this case you're trying to do something that would be invalid even if the array were a database object. You simply can't specify a variable as the target of an INSERT statement no matter what its declaration is. To do this correctly you need to use SELECT... BULK COLLECT INTO...:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
SELECT 'myaddy#internet.com' BULK COLLECT INTO g_to FROM dual;
END;
However, if you're just adding a static value into the array, you'd be better off skipping the context switch incurred by using SQL and insert the value directly:
DECLARE
TYPE array IS TABLE OF VARCHAR2(255);
g_to array DEFAULT array ();
BEGIN
g_to.extend
g_to(g_to.last) := 'myaddy#internet.com';
END;
I need to write a procedure with input parameters like groupid and item ids(array)
I need to insert into a table with values(groupid,itemid[0]) all items like (1,11),(1,12),(1,13),etc. I have table with two columns (groupid,itemid). please help me to sort out this problem. I am trying to write merge but getting error
CREATE OR REPLACE PROCEDURE update_product_group_prc
(
in_product_group_key IN INT,
in_product_key_array IN dbms_utility.maxname_array
)
AS
indx pls_integer := in_product_key_array.FIRST;
BEGIN
WHILE(INDX IS NOT NULL)
LOOP
MERGE INTO DIM_PRODUCT_X_GROUP PXG
USING(SELECT IN_PRODUCT_GROUP_KEY ,
IN_PRODUCT_KEY_ARRAY(INDX) IN_PRODUCT_KEY_ARRAY
FROM DUAL) IN_TBL
ON(IN_TBL.IN_PRODUCT_GROUP_KEY=PXG.PRODUCT_GROUP_KEY)
WHEN MATCHED THEN
-- DELETE --need to delete source records which r not here in array.
-- WHERE
WHEN NOT MATCHED THEN
INSERT (PRODUCT_GROUP_KEY,PRODUCT_KEY)
VALUES (IN_TBL.IN_PRODUCT_GROUP_KEY,IN_TBL.IN_PRODUCT_KEY_ARRAY);`
INDX := IN_PRODUCT_KEY_ARRAY.NEXT(INDX);
END LOOP;
END update_product_group_prc;
Error(16,41): PL/SQL: ORA-00936: missing expression
You have a syntax error. Comment the "WHEN MATCHED THEN" fragment.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm#SQLRF55028
I am trying to write a following PL/SQL function body for a dynamic action
The purpose of dynamic action is to set value for text area based on input parameters. Way I am trying to do it, is that setting the value into variable for different options
declare
P_NOTE varchar(100); -- derive value
P_WEBSERVER varchar(100); -- derive name
begin
-- for getting the P_NOTE value
select distinct note into P_NOTE from port_mapping where PLATFORM = :P3_PLATFORM and VERSION = :P3_VERSION;
-- for getting web server value
select CONCAT(P_NOTE,CONCAT('https-',:P3_CLIENT)) into P_WEBSERVER from dual order by 1;
if (:P3_PLATFORM = 'Apache') then
return P_WEBSERVER;
end if;
end;
However I am getting error
ORA-06550: line 15, column 5:
PLS-00372: In a procedure, RETURN statement cannot contain an expression
ORA-06550: line 15, column 5:
PL/SQL: Statement ignored
declare
P_NOTE varchar(100);
P_WEBSERVER varchar(100);
I am not sure what I am missing.
(Since you did not post any apex version this explanation deals with version 4.2)
If this -is- a dynamic action and the code you posted is in a true action of type 'Execute PL/SQL Code' then you can not use RETURN. The plsql block is not a function body (close, Mr Kemp!).
If you want to return values from the session state to page items then you need to use the "Page Items to Return" item of the true action.
This will put the session state of the defined page items into the value of the item on the page. This means that you can not use any variable to just put stuff in to be able to return it to the page, but you need to use an actual page item (after all, these are bind variables).
To clarify further, you would not write :
return P_WEBSERVER;
But you'd have to use a page item, say P3_WEBSERVER, and you'll need to create one if it doesn't exist of course:
:P3_WEBSERVER := p_webserver;
Of course you'd need to make sure that the correct value will be in there as you can not shortcircuit as you did in your code sample (p_webserver will usually hold a value even if the platform is not 'Apache') eg:
if (:P3_PLATFORM = 'Apache') then
:P3_WEBSERVER := P_WEBSERVER;
else
:P3_WEBSERVER := NULL;
end if;
Just read error message:
line 15, column 5
So, trouble caused by this line:
return P_WEBSERVER;
return not allowed in PL/SQL blocks, use output parameter to return a value.
Read Tom's answer to find out how to do that.