Oracle dynamic query - sql

I've a simple query, vanilla select statement to which I want to filter the values provided by the user.
SELECT A,B,C,D,E FROM TAB
WHERE ....
Here the WHERE is not fixed i.e the user may input values for C, so only C should be filtered, or D or E so on. The problem is due to the user telling- filter callerID between 1 and 10 etc, but the database column has a different name. So to form a working query I have to map callerID to the columnName. As this would be in a procedure I've thought of passing the csv of userInputColumnNames, csv of dbColumns and filter begin and start. Then laboriously extract the values and match the correct db column name and form the query. This works, but however this is very cumbersome and not clean. Could there be a better way of doing this?

Do the column names in the table change?
Or are columns in the table added/removed?
If not, you can generate a number to map to each column in the table like:
SQL> SELECT column_name, ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY column_name) "COLUMN_NUMBER"
2 FROM dba_tab_columns
3 WHERE table_name='DBA_USERS'
4
baim> /
COLUMN_NAME COLUMN_NUMBER
------------------------------ -------------
ACCOUNT_STATUS 1
CREATED 2
DEFAULT_TABLESPACE 3
EXPIRY_DATE 4
EXTERNAL_NAME 5
INITIAL_RSRC_CONSUMER_GROUP 6
LOCK_DATE 7
PASSWORD 8
PROFILE 9
TEMPORARY_TABLESPACE 10
USERNAME 11
USER_ID 12
12 rows selected.
Then when the user selects column 9, you know it maps to the "PROFILE" column.
If the column names can change, or if columns are added/dropped dynamically, then this won't work though.

Related

Why is this join not working in Oracle SQL

I am trying to output everything for table one where there is a mention like something from table two
table one is the aoldataleak from 2006 and table two is a created table of all contestants in a horse race at that time period
select query,
PFERDENAME
from AOLDATA.querydata,
Pferde
where query like ( '%' ||PFERDENAME||'%')
ORDER BY PFERDENAME;
Pferdename is a column in table 2 and query is a column in table one
both are chars and the output I get is just a blank table, but I know for a fact there are querys in the first table that are like Pferdenamen in the second one.
I tried this same statement with a dummy table with only a few entries and there it worked just fine
So here's error cause:
Pferdename CHAR (25) PRIMARY KEY
CHAR datatype right-pads values with spaces up to the max column length. So, if horse name is "Max", Oracle stores it as "Max" followed by 22 spaces (which alltogether make 3 + 22 = 25 characters).
You shouldn't
use CHAR in such a case; use VARCHAR2 instead
name is not the best choice for a primary key; it means that there can't be two horses whose names are "Max"
If it must be CHAR, then you'd better trim it, e.g.
select query, PFERDENAME
from AOLDATA.querydata, Pferde
where query like ( '%' || trim(PFERDENAME) ||'%')
ORDER BY PFERDENAME;
Example:
SQL> with
2 querydata (query) as
3 (select 'This is Max, my favorite horse' from dual),
4 pferde (pferdename) as
5 (select 'Max ' from dual)
6 select query, pferdename
7 from querydata, pferde
8 where query like ( '%' || trim(pferdename) ||'%')
9 order by pferdename;
QUERY PFERDENAME
------------------------------ -----------
This is Max, my favorite horse Max
SQL>

Selecting rows based on values in one of its semi-colon delimited columns: PL/SQL

I'm currently trying to select all rows where a certain ID exists within that rows semi-colon delimited ID column.
The Table:
=====================
TOOL_ID | TOOL_USERS
---------------------
1 1;2;3
2 1;3
3 1
=====================
I want to select all the tools that a certain user has access to, for example, the desired result where the user ID is 3:
TOOL_ID | TOOL_USERS
---------------------
1 1;2;3
2 1;3
I know that this design is not normalized, but I do not have the ability to change/modify the database. I could always just query all of the rows and then loop through the results deleting any that don't contain the user id, but I'd rather do this is one nice, clean query.
Is this possible?
Thanks.
You can use the LIKE keyword with wildcards. I included leading and ending semicolons so 13 and stuff doesn't match 3.
SELECT TOOL_ID, TOOL_USERS FROM YourTable WHERE ';' || TOOL_USERS || ';' LIKE '%;3;%'
Someone let me know if I didn't translate this well to PLSQL.

union table, change serial primary key, postgresql

Postgresql:
I have two tables 'abc' and 'xyz' in postgresql. Both tables have same 'id' columns which type is 'serial primary key;'.
abc table id column values are 1,2,3 and also xyz id column containing same values 1,2,3,4
I want to union both tables with 'union all' constraint. But I want to change 'xyz' id column values to next value of 'abc' id column last value as 1,2,3,4,5,6,7
select id from abc
union all
select id from xyz
|id|
1
2
3
1
2
3
4
my wanted resuls as
|id|
1
2
3
4
5
6
7
BETTER - Thanks to #CaiusJard
This should do it for you
select id FROM abc
UNION ALL select x.id + a.maxid FROM xyz x,
(SELECT MAX(id) as maxid from abc) a
ORDER BY id
For anyone who's doing something like this:
I had a similar problem to this, I had table A and table B which had two different serials. My solution was to create a new table C which was identical to table B except it had an "oldid" column, and the id column was set to use the same sequence as table A. I then inserted all the data from table B into table C (putting the id in the oldid field). Once I fixed the refernces to point to from the oldid to the (new)id I was able to drop the oldid column.
In my case I needed to fix the old relations, and needed it to remain unique in the future (but I don't care that the ids from table A HAVE to all be before those from table C). Depending on what your trying to accomplish, this approach may be useful.
If anyone is going to use this approach, strictly speaking, there should be a trigger to prevent someone from manually setting an id in one table to match another. You should also alter the sequence to be owned by NONE so it's not dropped with table A, if table A is ever dropped.

Sql to get unique rows

I have a table as below.
OId CustId CustSeq
1 A 10
1 A 20
2 A 10
2 A 20
I'm trying to extract unique records as below.
OId CustId CustSeq (Different OIds with different CustSeqs)
1 A 10
2 A 20
May I know how I could come out the query to extract like above?
Just use DISTINCT. That's what it was desgined for although group by will work.
http://www.techonthenet.com/oracle/distinct.php
SELECT DISTINCT OID, CUSTID, CUSTSEQ
FROM TABLE_NAME
Use DISTINCT, and also use Group By for the 2 columns CustId & CustSeq
Check here for example Is it possible to GROUP BY multiple columns using MySQL?

PostgreSQL columns to rows with no explicilty specifying column names / columns

I would like to know is there any way to do unpivot (turn columns to rows) data in PostgreSQL.
For example, if I have a table like:
ID Name Age
1 Alice 16
2 Bob 21
3 Carl 18
I want to get an output like
ID Column_Name Column_Value
1 Name Alice
1 Age 16
2 Name Bob
2 Age 21
3 Name Carl
3 Age 18
I know I could do it like (sql fiddle with data to try it):
select
U.ID,
unnest(array['Name', 'Age']) as Column_Name,
unnest(array[U.Name, U.Age::text]) as Column_Value
from Users as U
But is there any way I could do it for all columns in table without explicitly specifying column names?
For example, for SQL Server I know of at least 2 ways to do it - dynamic SQL or turn data into xml and parse xml - SQL Server : Columns to Rows. May be there's some xml trick in PostgreSQL too?
With hstore extension:
SELECT id, skeys(hstore(users)) AS column, svals(hstore(users)) AS value FROM users;