Run SQL through JDBC, how to parameterize Table Names - oracle

If I have two tables:
CREATE TABLE Test_Persons_A
(
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_A (PersonID, LastName, FirstName)
VALUES (11, 'LN_A1', 'FN_A1');
INSERT INTO Test_Persons_A (PersonID, LastName, FirstName)
VALUES (12, 'LN_A2', 'FN_A2');
CREATE TABLE Test_Persons_B
(
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_B (PersonID, LastName, FirstName)
VALUES (21, 'LN_B1', 'FN_B1');
INSERT INTO Test_Persons_B (PersonID, LastName, FirstName)
VALUES (22, 'LN_B2', 'FN_B2');
commit;
The effect I want to achieve is equivalent to executing each the following two queries from java code through JDBC (oracle)
Block A:
select PersonID as PID, LastName as LN, FirstName as FN
from Test_Persons_A tp
where tp.LASTNAME like '%1%'
Block B:
select PersonID as PID, LastName as LN, FirstName as FN
from Test_Persons_B tp
where tp.LASTNAME like '%2%'
You can see that the only difference are:
Table Name
LASTNAME cretiria
But in my case, each of the the blocks are in fact a huge 'With...Select...' clause, and the java code (legacy, I can't change an iota) in fact reads each sql block from a .sql file as below before executing it through JDBC.
hugeQueryA.sql
hugeQueryB.sql
My question is: to avoid duplicating this huge block of code, instead, is it the best to construct a single large stored procedure (or functions)?
hugeStoredProc
put it in my DB, then construct two simple sql
simpleQueryA.sql
simpleQueryB.sql
to call the stored procedure with parameters (specified in each of the sql)?
Can I do this without having to use Dynamic SQL (since to do that I assume I will need change the content of the original huge sql files into strings and handle all the special chars - plus, would that also going to look awful?)?
More generally, when I need to 'parameterize' the table name, and can't use 'substitution variables', is dynamic SQL the only way to go?

Table names can't be parameterized, but you can use string substitution to generate the desired SQL after loading in your .sql file(s), provided the table names you're substituting in aren't based on user input.
For example, you could change:
from Test_Persons_A tp
to:
from {TableName} tp
After you load the file, use string substitution to replace "{TableName}" with the actual table name, then execute.

Related

(Beginner) How to exclude null value from Oracle Inner Join Statement Result and How to show ONLY null data in any of the attributes

(Beginner)
Q1) How to exclude null value from Oracle Inner Join Statement Result. i.e. to display only that row which has all the values (i.e. no null data in any of the attribute)
Q2) How to show ONLY those record/s who has missing/null data in any of the attributes in any of the four table
Below is the dummy example in oracle sql
Created 4 Tables i.e.,
name , details , social , address
`create table name
(
id number,
firstname varchar2(20),
lastname varchar2(20)
);
create table details
(
id number,
dob_month varchar2(20),
dob_day varchar2(20),
dob_year varchar2(20)
);
create table social
(
id number,
ssn varchar2(20),
telephone number
);
create table address
(
id number,
address varchar2(20)
);
`
Now insert dummy data into the above tables
`insert into name values (1, 'Will' , 'Smith');
insert into name values (2, 'Barry' , 'White');
insert into name values (3, 'Tom' , 'Jones');
insert into name values (4, 'Rod' , 'Stewart');
insert into name values (5, 'Elvis' , 'Presley');
insert into details values (1,'May',31,null);
insert into details values (2,'August',22,1980);
insert into details values (3,'October',null,1973);
insert into details values (4,'January',30,1980);
insert into details values (5,'March',11,1980);
insert into social values (1,'123-45-6789',null);
insert into social values (2,'222-45-5555',789456123);
insert into social values (3,'333-45-7777',888888888);
insert into social values (4,null,693456741);
insert into social values (5,'999-45-1111',null);
insert into address values (null, null);
insert into address values (2, '12th street');
insert into address values (null, null);
insert into address values (4, '14th Avenue');
insert into address values (5, null);`
Q1 Pictorial Explanation
For Q1,
I tried with below oracle sql query (both returns the same result) but not able to figure out the exact query which will exclude null value from Oracle Inner Join Statement Result and display only that row which has all the values (i.e. not null)
`select name.id, firstname, lastname, dob_month, dob_year, ssn, telephone, address
from name, details, social, address
where name.id=details.id
and details.id=social.id
and social.id=address.id;
select name.id, firstname, lastname, dob_month, dob_year, ssn, telephone, address
from name join details on name.id=details.id
join social on details.id=social.id
join address on social.id=address.id;`
For Q2, I am looking for sample Query
i.e. How to show ONLY those record/s who has missing/null data in any of the attributes in any of the four table
For the first question, I think you are looking for this:
select name.id, firstname, lastname, dob_month, dob_year, ssn, telephone, address
from name
join details on name.id=details.id
join social on details.id=social.id
join address on social.id=address.id
where dob_year is not null
and dob_day is not null
and telephone is not null
and ssn is not null
and address is not null;
Or a bit shorter
...
where COALESCE(dob_year, dob_day, telephone, ssn, address) is not null;
For Q2 it would be this
select *
from address
where id is null
or address is null;
Some more notes:
It is a poor design to store date parts and then even localized strings. You should never do that. In your case it should be
create table details
(
id number,
dob_date DATE
);
Then next question, why do you create four tables? Maybe you learned at school about database normalization but you have taken too literally. Can a person have more than one SSN/telephone? If not, then add these columns to name table (and maybe rename it to person) instead of a separate table. The same question applies to table address.

Strategy to snapshot large data set Oracle

My Problem:
I have an app and users who login have a department authorization list:
DEPT1, DEPT2, DEPT3, ..., DEPT5000, DEPT5001, ...
Most users have 5,000+ departments assigned to their profile.
I am tasked with writing a data model + application code that will 'snapshot' their list of authorized departments every time a user logs in so that we may refer to what that user was authorized to do (note: the DEPT IDs are not neatly numbered like in this example).
What I've tried:
My first thought was to turn the list of departments into a long CSV string and store it as a CLOB:
CREATE TABLE UI_SECURITY_CONFIG (
SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
DEPTSCSV CLOB NOT NULL
);
And each DEPTSCSV CLOB would be unique. If the user has the same security profile as someone else who's logged in previously, it would just select that security config. Otherwise, it would create a new row. Basically, do a select where DEPTSCSV = 'DEPT1, DEPT2, DEPT3 ...' and if it doesn't exist, insert it. But this approach failed because a huge string that big (25,000+ chars) isn't comparable:
SELECT * FROM UI_SECURITY_CONFIG WHERE DEPTSCSV = 'DEPT0001, DEPT0002, DEPT0003, ..., DEPT5001, DEPT5002'
SQL Error [1704] [42000]: ORA-01704: string literal too long
Solution attempt #2:
So then I thought about making each item in the CSV its own row in the table:
CREATE TABLE UI_SECURITY_CONFIG (
SECURITY_CONFIG_ID NUMBER(19,0) NOT NULL,
DEPTID VARCHAR2(20) NOT NULL
);
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0002');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT0003');
...
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5001');
INSERT INTO UI_SECURITY_CONFIG(SECURITY_CONFIG_ID, DEPTID) VALUES(1, 'DEPT5002');
But I'm struggling to write the SQL select that would be an efficient matching algorithm to find if a SECURITY_CONFIG_ID exists that matches exactly the list of Departments.
I'm not even sure there is an efficient way to solve this problem.
Solution Attempt #3:
Ask Stack Overflow. What would you do?
I was able to achieve strategy #1. The Application code (Java) handled the CLOB comparison better than my SQL client (DBeaver) with PreparedStatement:
String sql = "SELECT SECURITY_CONFIG_ID FROM UI_SECURITY_CONFIG WHERE dbms_lob.compare(DEPTSCSV, ?) = 0";
String DEPTSCSV = "DEPT0001, DEPT0002, ...";
try(PreparedStatement objStmt = objConn.prepareStatement(sql)) {
Clob clob1 = objConn.createClob();
clob1.setString(1, DEPTSCSV);
objStmt.setClob(1, clob1);
ResultSet result = objStmt.executeQuery();
...
}

Loading Data into an empty Impala Table with account data partitioned by area code

I'm trying to copy data from a table called accounts into an empty table called accounts_by_area_code. I have the following fields in accounts_by_area_code: acct_num INT, first_name STRING, last_name STRING, phone_number STRING. The table is partitioned by areacode (the first 3 digits of phone_number.
I need to use a SELECT statement to extract the area code into an INSERT INTO TABLE command to copy the speciļ¬ed columns to the new table, dynamically partitioning by area code.
This is my last attempt:
impala-shell -q "INSERT INTO TABLE accounts_by_areacode (acct_num, first_name, last_name, phone_number, areacode) PARTITION (areacode) SELECT STRLEFT (phone_number,3) AS areacode FROM accounts;"
This generates ERROR: AnalysisException: Column permutation and PARTITION clause mention more columns (5) than the SELECT / VALUES clause and PARTITION clause return (1). I'm not convinced I have even the basic syntax correct so any help would be great as I'm new to Impala.
Impala creates partitions dynamically based on data. So not sure why you want to create an empty table with partitions because it will be auto created while inserting new data.
Still, I think you can create empty table with partitions like this-
impala-shell -q "INSERT INTO TABLE accounts_by_areacode (acct_num) PARTITION (areacode)
SELECT CAST(NULL as STRING), STRLEFT (phone_number,3) AS areacode FROM accounts;"

Cassandra INSERT Column Set<text> Does Not Persist

The problem is that when I INSERT a row into a Cassandra table. A column(ciderblocks) does not appear to be persisting. No exception is generated. Following is my schema,
CREATE TABLE atlascarpenter.registration (
id timeuuid PRIMARY KEY,
email text,
firstname text,
lastname text,
cidrblocks set<text>
);
My insert is this,
INSERT INTO atlascarpenter.registration
(id, cidrblocks, email, firstname, lastname)
VALUES
(now(), {'222.222.222.0/10','111.111.111.0/10'}, 'john.doe#google.com', 'john', 'doe');
My query and results are this,
select * from atlascarpenter.registration
id, cidrblocks, email, firstname, lastname
54ca6860-6b47-11e6-8ddf-c9ea2c0bd7d2 [] jane.doe#company.com jane doe
Any idea why cidrblocks is empty?
Turns out the problem is RazorSQL. If I dump the schema or the contents of the table using Cassandra's cqlsh tool I see correct schema and data as expected. RazorSQL's tool indicated it was compatible with Cassandra but unfortunately it does not appear to support all Cassandra data types. Or at least it does not support multi-valued types like list and set. Strange I'm posting my own reply as an answer but I thought this might be helpful to someone else.

Hive partitions on tables

when we partition a table the columns on which the table is being partitioned are not mentioned in the create statement and separately used in the partitioned by.What is the reason behind this.
CREATE TABLE REGISTRATION DATA (
userid BIGINT,
First_Name STRING,
Last_Name STRING,
address1 STRING,
address2 STRING,
city STRING,
zip_code STRING,
state STRING
)
PARTITION BY (
REGION STRING,
COUNTRY STRING
)
The partition that we create in hive makes a pseudocolumn on which we can query directly without having them in create statement.
So when we include partition column on the data of the table itself(create query) we will be getting error like 'Error in semantic analysis. Columns repeated in partitioning columns'

Resources