I'm required to write a couple of UPDATE queries to parse data from a .csv file, but i do not know how the table works, i don't even have direct access to the Database, i just got an INSERT query like this one :
insert into lr_umbrales_valores (umcod_id, uvfec_dt, uvval_nm)
values ((select umcod_id from lr_umbrales
where lrcod_nm = (
select lrcod_id from lr_lineas_referencia
where me_metrica_nm = ?
and fecha_baja_dt is null)
and umtip_tx='S'), sysdate, ?)
So i'm trying this :
UPDATE LR_UMBRALES_VALORES SET UVVAL_NM = ?
WHERE (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
AND UVFEC_DT = TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS')");
This gives me a 'Missing Expression' Error (ORA-00936)
This is the only Information about the tables i got :
This is the Table i need to Update (its UVVAL_NM)
From this one, i get the UMCOD_ID when LRCOD_NM is the same as the LRCOD_ID from the next table.
Get the LRCOD_ID when ME_METRICA_NM is the same as the '?' parameter
Any tip in how to approach this? Needless to say, i'm completely new with SQL so this may be a very obvious mistake but i cannot get it right.
This part
WHERE (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
causes the error. Maybe you wanted something like
WHERE UMCOD_ID = (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
Related
I have the below SP which I am trying to convert into simple Java inline query :
CREATE OR REPLACE PROCEDURE public.spdummytable(
par_zone_no integer,
par_fpsallocid integer,
INOUT p_refcur refcursor)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
OPEN p_refcur FOR
SELECT
z.zone_no,
m AS monthnumber,
COALESCE(fpsallocid, par_FPSallocid) AS fpsallocid,
to_char((CAST ('2000-01-01' AS TIMESTAMP WITHOUT TIME ZONE))::TIMESTAMP + (COALESCE(aw.month, m) - 1::NUMERIC || ' MONTH')::INTERVAL, 'Month') AS monthname,
week1,
week2,
week3,
week4
FROM (SELECT par_Zone_No AS zone_no) AS z
CROSS JOIN (SELECT 1 AS m
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10
UNION SELECT 11
UNION SELECT 12) AS moty
LEFT OUTER JOIN anotherTable AS aw
ON z.zone_no = aw.zone_no AND
aw.month = moty.m AND
COALESCE(fpsallocid, par_FPSallocid) = par_FPSallocid;
END;
$BODY$;
ALTER PROCEDURE public.spdummytable(integer, integer, refcursor)
OWNER TO postgres;
This will fetch some weekly values for every month from Jan to Dec.
What I am trying is below :
public List<MyResponse> result = null;
Connection conn = DatabaseConnection.connect();
PreparedStatement stmt = conn.prepareStatement("call public.spdummytable(?,?,?,,....,cast('p_refcur' as refcursor)); FETCH ALL IN \"p_refcur\";");
stmt.setString(1, "8006");
stmt.setString(2, "8049");
----
----
boolean isResultSet = stmt.execute();
if(isResultSet) {
ResultSet rs = stmt.getResultSet();
while(rs.next()) {
MyResponse myResponse = new MyResponse();
myResponse.setSomeVariable(rs.getString("columnname"));
-----
-----
result.add(myResponse)
}
rs.close();
conn.close();
}
But I am confused on the query formation part from the above SP. This seems to be a complex conversion. Can someone please help form the inline query. Appreciate your help on this.
EDIT/UPDATE
If I am unable to explain myself, I just want to say that I need to form the postgresql SELECT query from the above SP. I know the PreparedStatement is wrong above, I am trying to form a basic sql query from the above SP . Changing/Modifying the SP is not an option for me. I am planning to cut the dependency from the database and control it over Java. Please help.
I don't think getResultSet works with a stored procedure like that but I'm unsure. You're operating on a cursor with your INOUT parameter. As suggested in the comments, this would be much easier with a set returning function.
Note: stored procedures didn't exist in Postgres before Postgres 11.
If you cannot convert this to a set returning function, you'll need to handle the cursor object in a different manner. Something like this:
CallableStatement stmt = conn.prepareCall("{? = call public.spdummytable(?,?) }");
stmt.registerOutParameter(1, Types.OTHER);
stmt.setString(2, "8006");
stmt.setString(3, "8049");
stmt.execute();
ResultSet results = (ResultSet) stmt.getObject(1);
while (results.next()) {
// do something with the results.
}
Set returning function:
CREATE OR REPLACE FUNCTION public.spdummytable
( par_zone_no INTEGER
, par_fpsallocid INTEGER
)
RETURNS TABLE ( zone_no INTEGER -- I don't know the data types of these fields
, monthnumber INTEGER
, fpsallocid INTEGER
, monthname TEXT
, week1 TEXT
, week2 TEXT
, week3 TEXT
, week4 TEXT
)
AS $$
BEGIN
RETURN QUERY
SELECT z.zone_no AS zn
, moty AS mo_num
, COALESCE(fpsallocid, par_FPSallocid) AS fpsid
, to_char((CAST ('2000-01-01' AS TIMESTAMP WITHOUT TIME ZONE))::TIMESTAMP + (COALESCE(aw.month, m) - 1::NUMERIC || ' MONTH')::INTERVAL, 'Month') AS mo_name
, week1 w1
, week2 w2
, week3 w3
, week4 w4
FROM (SELECT par_Zone_No AS zone_no) AS z
CROSS JOIN generate_series(1, 12) AS moty
LEFT OUTER JOIN anotherTable AS aw ON z.zone_no = aw.zone_no
AND aw.month = moty
AND COALESCE(fpsallocid, par_FPSallocid) = par_FPSallocid
;
END;
$$ LANGUAGE PLPGSQL;
You could also define your own return type and use RETURNS SETOF your_type. Use the same function body as above.
CREATE TYPE type_dummytype AS
( zone_no INTEGER -- I don't know the data types of these fields
, monthnumber INTEGER
, fpsallocid INTEGER
, monthname TEXT
, week1 TEXT
, week2 TEXT
, week3 TEXT
, week4 TEXT
);
CREATE OR REPLACE FUNCTION public.spdummytable
( par_zone_no INTEGER
, par_fpsallocid INTEGER
)
RETURNS SETOF type_dummytype
AS $$ ... $$
Then your prepared statement becomes something like this:
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM public.spdummytable(?, ?);");
stmt.setString(1, "8006");
stmt.setString(2, "8049");
All of the other java should be good to go.
I have create a query in orm lite like this :
TAbleA.queryBuilder()
.where()
.eq("col1", Wait)
.or()
.eq("col2", Fail)
.and()
.isNull("col3")
.or()
.le("col4", fromThisTime)
.prepare();
it prepare this query :
MappedStatement: SELECT COUNT(*) FROM `TableA` WHERE (((`col1` = 'Wait' OR `col2` = 'Fail' ) AND `col3` IS NULL ) OR `col4` <= '2018-11-18 13:08:03.637000' )
but I want to change it to :
MappedStatement: SELECT COUNT(*) FROM `TableA` WHERE (`col1` = 'Wait' OR `col2` = 'Fail' ) AND (`col3` IS NULL OR `col4` <= '2018-11-18 13:08:03.637000' )
how can I do it ?!
I want to change AND and OR order.
can Someone help me?
according to this the easiest way is :
TAbleA.queryBuilder()
.where()
.eq("col1", Wait)
.eq("col2", Fail)
.or(2)
.isNull("col3")
.le("col4", fromThisTime)
.or(2)
.and(2)
.prepare();
otherwise you can write your complex query using post-order
I am using PreparedStatement for executing the update query.
The following is the query:
String callersUpdateQuery = "update W67U999S a set pcrdattim= ? where exists (select b.CRDATTIM, b.RECORDCD, b.CRNODE, b.UNITCD, b.WRKTYPE from W03U999S b where a.PCRDATTIM = ? and a.CCRDATTIM = b.CRDATTIM and a.CRECORDCD = b.RECORDCD and a.CCRNODE = b.CRNODE and a.PRECORDCD = 'F' and a.PCRNODE = '01' and b.WRKTYPE = 'CALLER' and b.UNITCD=? and a.crecordcd='T')";
The below is the java code that should update the records:
preparedStatement = dbConnection.prepareStatement(callersUpdateQuery);
preparedStatement.setString(1,newFolderCrdattim);
preparedStatement.setString(2,crdattim);
preparedStatement.setString(3,businessAreaName.trim());
int j = preparedStatement.executeUpdate();
But preparedStatement.executeUpdate() is not updating the required rows and returning the updated rows count as zero. Weirdly, the same sql query when I execute at the database end, the records are getting updated.
My database is Oracle and the schema of the table that should be updated is below:
Name Null Type
----------- -------- ----------
PCRDATTIM NOT NULL CHAR(26)
PRECORDCD NOT NULL CHAR(1)
PCRNODE NOT NULL CHAR(2)
RECORDTYPE NOT NULL NUMBER(3)
CCRDATTIM NOT NULL CHAR(26)
CRECORDCD NOT NULL CHAR(1)
CCRNODE NOT NULL CHAR(2)
CRDATTIM NOT NULL CHAR(26)
LINKRULE_ID NOT NULL NUMBER(14)
Can anyone guess what's wrong with the code or query?
First, did you check for existence of tuples on the select you're using as condition in where clause?
If there are rows being returned. The issue may be related to the transaction in which you're executing your update statement. Double check for your transaction mode and if it is really being committed.
As a query optimization suggestion I'd change the statement to:
String callersUpdateQuery =
"update W67U999S a
set pcrdattim= ?
where
a.PCRDATTIM = ?
and a.PRECORDCD = 'F'
and a.PCRNODE = '01'
and a.CRECORDCD ='T'
and exists (
select
b.CRDATTIM,
b.RECORDCD,
b.CRNODE,
b.WRKTYPE
from W03U999S b
where
b.CCRDATTIM = a.CRDATTIM
and b.CRECORDCD = a.RECORDCD
and b.CCRNODE = a.CRNODE
and b.WRKTYPE = 'CALLER'
and b.UNITCD=?
)";
That way you will be first reducing the tuples from a then use it to narrow the b tuples only to those that match.
Oracle CHAR type is the culprit here. The columns that I want to update are of type CHAR. That's causing the issue. This link helped me in figuring out the solution: Oracle JDBC and Oracle CHAR data type
I need to insert a huge amount of data in a table that is in FK with another one that has a two big fields in Eager.
The HQL query is:
insert into DeviceAuthorizationEntry (id, osc, moduleName, delegateModule, functionName, groupName, owner)
select concat(item0.id.uuid, '1413971469473'), item0.osc, 'aaaaaaaa',
'devices', 'view_devices', 'administrator', item0
from device.model.Device as item0
where item0.osc IN (:oscNameList0)
and item0.nodeTypeDefinition.QN IN (:nodeTypesList0)
and not exists (select 1 from device.model.DeviceAuthorizationEntry as auth
where auth.moduleName != 'aaaaaaa'
and auth.delegateModule != 'devices'
and auth.functionName != 'view_devices'
and auth.groupName != 'administrator'
and auth.owner != item0 )
But the one executed on Oracle is:
INSERT
INTO DeviceAuthorizationEntry
(
id,
osc,
moduleName,
delegateModule,
functionName,
groupName,
owner_uuid
)
SELECT device0_.uuid
||'1413965664136' AS col_0_0_,
device0_.osc AS col_1_0_,
'aaaaaaaa' AS col_2_0_,
'devices' AS col_3_0_,
'view_devices' AS col_4_0_,
'administrator' AS col_5_0_,
device0_.uuid AS col_6_0_
FROM dem_device device0_,
cor_noddef nodetypede1_
WHERE device0_.uuid_ndtypedef=nodetypede1_.uuid
AND 1 =1
AND (device0_.osc IN (? , ?))
AND (nodetypede1_.QN IN (? , ? , ? , ? , ? , ? , ? , ? , ?))
AND NOT (EXISTS
(SELECT 1
FROM DeviceAuthorizationEntry deviceauth2_
WHERE deviceauth2_.moduleName <>'aaaaaaaa'
AND deviceauth2_.delegateModule<>'devices'
AND deviceauth2_.functionName <>'view_devices'
AND deviceauth2_.groupName <>'administrator'
AND deviceauth2_.owner_uuid <>uuid
))
As you can see in the last "and" of the exists subquery, hibernate does not precede the "uuid" field with the alias "device0_".
Hibernate supports the insert into select as you can see here https://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch11.html#d5e2610
I don't know where I'm wrong.
I am writing one application to search for specific fields in the form and display the corresponding query to the user (user can save the executed query and load the query later). I am using an API to generate the query based on the selected fields. The API returns the generated query in following format.
Generated query:
SELECT T0."id" AS "COL0"
FROM student_table T0
WHERE ( ( ( T0."student_name" = ? )
AND ( T0."grade" = ? ) )
AND ( T0."student_no" LIKE ? ) )
Expected query:
SELECT T0."id" AS "COL0"
FROM student_table T0
WHERE ( ( ( T0."student_name" = 'John' )
AND ( T0."grade" = 'A' ) )
AND ( T0."student_no" LIKE '12%' ) )
Now I have to build proper query from above query. Since I have the field values in the from, I want to replace the "?" with corresponding values.
Is it possible to replace the '?' with corresponding field values using java string replaceAll method ? can we use the concept of back references to replace the question marks with corresponding values ? If not possible with regex please suggest a better approach to solve the problem.
Edit
I think prepared statement wont help much since I need to automate this process for hundreds of fields which are unordered and it is a very costly operation also. (correct me If I am wrong)
I am actually using my company specific platform API, I am adding criteria's and query columns to the query definition and it returns the executed query in the above mentioned format. User should be able to save the Expected query, I should display both the query and result of query in UI.
Try to execute query in following way
String insertTableSQL = "SELECT T0.\"ID\" AS \"COL0\" FROM STUDENT_TABLE T0 WHERE ( ( ( T0.\"STUDENT_NAME\" = ? ) AND ( T0.\"GRADE\" = ? ) ) AND ( T0.\"STUDENT_NO\" LIKE ? ) )";
PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setString(1, "John");
preparedStatement.setString(2, "A");
preparedStatement.setString(3, "12%");
preparedStatement.execute();
You can use PreparedStatement to execute such queries that contains ?
PreparedStatement ps = null;
ResultSet rs = null;
String sQuery = "SELECT T0."ID" AS "COL0" FROM STUDENT_TABLE T0 WHERE ( ( ( T0."STUDENT_NAME" = ? ) AND ( T0."GRADE" = ? ) ) AND ( T0."STUDENT_NO" LIKE ? ) )";
ps = objConnection.prepareStatement(sQuery);
ps.setString(1, valueOf_T0."STUDENT_NAME");
ps.setString(2, valueOf_T0."GRADE");
ps.setString(3, valueOf_T0."STUDENT_NO");
rs = ps.executeQuery();
As you have data values and you know the type of database fields, so that you can set values in setter methods according to your data type like setInt(), setDouble(),etc.
Read more about : http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html
Thanks