Succinct Version:
I'm looking for a C++ OCI adaptation of the following Java technique, where code is able to bind an array of numbers (the array size can vary) into a non-PL/SQL SELECT
statement and then use the resulting array in a WHERE ID IN (...)
style check.
http://rafudb.blogspot.com/2011/10/variable-inlist.html
Original Question:
We have a C++ app which talks to Oracle via OCI. We're trying to fix old code which generates SQL queries by concatenating text; instead we want to use bind variables as much as possible. One particular case has come up that we don't have a good solution for.
SELECT * FROM MyTable WHERE ID IN (1, 4, 10, 30, 93)
Where the (1, 4, 10, 30, 93)
part comes from a vector<int>
or some other flexibly-sized container of data. If we knew it would always be five values, we could do:
SELECT * FROM MyTable WHERE ID IN (:1, :2, :3, :4, :5)
But it might be one entry, or ten, or maybe even zero. Obviously, if we are building up the query as a string, we can just append as many numbers as we need, but the goal is to avoid that if possible and stick to just bind variables.
Is there a good way to accomplish this? For instance, in OCI, can I bind an array and then sub-select out of it?
SELECT * FROM MyTable WHERE ID IN (SELECT * FROM :1)
Where :1
is an OCI array? (Probably the syntax would differ.) Does anyone have experience with this? Sample code would be a godsend as I tend to struggle with writing raw OCI. Thanks :)
EDIT: I'd like to do better than binding in a string which is parsed by a PL/SQL procedure, if at all possible. I am confident that we would blow out the 4000 character limit in many cases, and I also feel like that's just trading one kind of string manipulation that I'm comfortable with, for another kind that I'm not (and I can't debug as easily). If possible I'd like to bind an array of values (or some form of dataset) into one standard SQL statement.
EDIT 2: Some investigation turned up the following link which seems to be doing just what I want, but in Java: http://rafudb.blogspot.com/2011/10/variable-inlist.html Does anyone know how to adapt this approach to C++ OCI?
This example demonstrates approach with using collection type, defined in database to pass list of parameters.
SYS.ODCINumberList
is standard collection type available for all users. Query, used in sample just select first 100 integers ( test ) and then filter this integers with list inIN(...)
clause.You can use various ODCIxxxList types to pass list of numbers, dates or strings to Oracle via OCI or even define your own type in DB.
Example compiled with Visual Studio 10 Express and this version of OCI libraries. Tested against Oracle 11.2.0.3.0 .
Update
Below is example application which does same thing but with plain C OCIxxx functions.
P.S. You can get info from Oracle documentation and this example code.