need help to form a optimised update sql query - sql

I have a select query with where clause and want to write an update for the same condition.
But I am unable to form one.
So I get the output resultSet and traverse the resultSet to update the table [see below]
The select query:
select
a.businesskey, a.featurekey, c.businesskey, c.featurekey
from
device a,
(select concat(‘customPrefix’,ipaddr,’]’) clmna, instance_id
from wirelessdevice) as b,
device c
where
a.businesskey = b.clmna
and c.uniqueid = b.instance_id;
Present method to update:
string strQuery = "select a.businesskey, a.featurekey, c.businesskey, c.featurekey from device a, (select concat(‘customPrefix’,ipaddr,’]’) clmna, instance_id from wirelessdevice) as b, device c where a.businesskey=b.clmna and c.uniqueid=b.instance_id;";
ResultSet resultSet = statement.executeQuery();
while(resultSet.hasnext()){
String srcbkey = resultSet.getString(1);
String srcFtrkey = resultSet.getString(2);
String destBkey = resultSet.getString(3);
String destFtrkey = resultSet.getString(4);
String updateQuery = "update device set featurekey ='" + destFtrkey +"' where businesskey ='" + srcFtrkey +"';";
statement.executeQuery(updateQuery);
}
is it possible to write a single update query instead of recursively going through the resultset ?

Yes. I find your code hard to follow, but it is something like this:
update device d
set d.featurekey = concat('customPrefix', wd.clmna, wd.ipaddr, ']')
from wirelessdevice wd
where d.businesskey= wd.clmna and
d.uniqueid= wd.instance_id;

Related

Query to retrieve all row data for supplied column name

I am using Eclipse and Oracle SQL Developer. My connections are all set up. I am trying to query my database in SQL Developer by passing in a column name as a variable.
For example, I just want to use something similar to this statement:
select * from CUSTOMERS;
but allow CUSTOMERS to be a variable where I can pass in any table name.
Currently this pulls all column names from given column name and connection:
final String query = "select column_name from all_tab_columns"
+" where owner = ?"
+" and table_name = ?";
try {
headers = DAO.useJNDI(jndi)
.setSQL(query)
.input(1, host)
.input(2, tableName)
.list(String.class);
I want to do the same thing but with rows. Does anyone know how to do this? This is what I am thinking about so far:
final String sql = "select *"
+ " from table_name"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, host)
.input(2, tableName)
.list(DatabaseCompareDto.class);
The main focus is the SQL statements. I know everything else works.
If I'm reading your question correctly, I think what you want is to replace the first table_name in your SQL with ?, then add an additional .input( 1, tableName) :
final String sql = "select *"
+ " from ?"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, tableName)
.input(2, host)
.input(3, tableName)
.list(DatabaseCompareDto.class);
You can't pass the table name as a parameter. Instead of wasting your energy on such an alleged generic solution, use or create a small templating engine which allows you to replace the table name in your query before sending it to the database.

Order of JSON returned by ORMLite?

I'm new to web services and trying to query some tables using ORMLite, it doesn't support join statements so I'm using a raw query. I was wondering if there is a way to specify how the JSON is returned. What I have right now is:
Dao<CodesModel,String> CodesDao = DaoManager.createDao(connectionSource, CodesModel.class);
GenericRawResults<String[]> rawResults =
CodesDao.queryRaw(
"select r.CodeA, s.SubCodeA, r.CodeB, s.SubCodeB " +
"from CodesTable r JOIN SubCodesTable s ON s.CodeA = r.CodeA " +
"where SubCodeB = '" + b_sub + "' AND r.CodeB = '" + b_code + "'");
And the results are returned as a String[] and always seem to be in the order of
[CodeA, SubCodeA, CodeB, SubCodeB]
but I have only tested this locally and can't find in the documentation what determines the order for variables in the array that is returned.
The results are ordered that way because that is the order in which you specified them in the select statement. If you want the results ordered in a different way, reorder them in your query.
If anyone is looking for a way to know column names when using "select *" you can also use "getColumnNames()" on the rawResults object and they will always be in the order that the results are. Examples
//The result is returned as a GenericRawResults object
List<String[]> results = rawResults.getResults();
String[] columns = rawResults.getColumnNames();
JSONObject obj = new JSONObject();
if(results.size()>0)
{
obj.put(columns[0], results.get(0)[0]);
obj.put(columns[1], results.get(0)[1]);
obj.put(columns[2], results.get(0)[2]);
obj.put(columns[3], results.get(0)[3]);
}

Write a Query based on a Query - Not Working With Concatenation

I need to create a datasource for a combobox using a Linq to SQL query.
i.e. cboFindPerson.DataSource = LQPersonList
(where LQPersonList is a query)
But this time, I need to first concatenate the LastName and FirstName fields, and then order by the FullName, like this.
'-- Create the first Query with concatenation
Dim LQ = From b In DCAppMain.tblPeopleMain
Where b.PeopleID = lngPeopleID And b.CurrentEmployee = True
Select FullName = b.LastName & ", " & b.FirstName, b.PeopleID
'-- Create the 2nd Query based on first so I can order by FullName
Dim LQPersonList = From c In LQ
Order By c.
But when I get to c., intellisense says no fields are available.
I've written queries based on queries before w/o issue. I've also concatenated fields w/o issue. But apparently putting the two together is an issue.
I've been searching on this for several hours now, but can't find an answer that is on target.
Instead of using:
Dim LQ = From b In DCAppMain.tblPeopleMain
Where b.PeopleID = lngPeopleID And b.CurrentEmployee = True
Select FullName = b.LastName & ", " & b.FirstName, b.PeopleID
you need to use:
Dim LQ = From b In DCAppMain.tblPeopleMain Where b.PeopleID = lngPeopleID And
b.CurrentEmployee = True Select New With{.FullName = b.LastName & ", " &
b.FirstName, .PeopleID = b.PeopleID}
this is because when you pull individual properties out of a LINQ statement you end up with an IEnumerable(Of AnonymousType) which is fine but if you want intellisense to pick up the values that you are pulling out of your collection of objects then you need to assign them names.
So using the second LINQ statement you are basically creating a constructor for the anonymous type that also defines the properties FullName and PeopleID on the anonymous objects that make up the collection returned by the LINQ statement.

ebean query with subquery

I'm trying to do using EBean the equivalent of
select * from myTable1 where id not in (select id2 from myTable2) ;
I have no reference of table1 Object in table2 Object and the same the other way around.
Does anyone knows how to that using EBean ?
For the moment all I have is :
List<MyTable1> myResult = MyTable1.find.where().eq("id","1" ).findList();
Thanks.
C.C.
Apparently it has been possible to do this since 2009 using the example given in this bug report:
http://www.avaje.org/bugdetail-92.html
The example:
Query<Product> subQuery =
Ebean.createQuery(Product.class)
.select("sku")
.where().idEq(4).query();
List<MinCustomer> list = Ebean.find(MinCustomer.class)
.where().in("name", subQuery)
.findList();
However:
I am unable to make it work because the SQL generated is invalid. Seemingly due to a string replacement happening behind the scene in Ebean where (for me at least) the table name in the subquery is lost.
I expect it has to do with my main query includes a reference to the table from which my subquery "is selecting".
Turning the valid SQL from the example:
select c.id, c.name, c.notes
from o_customer c
where (c.name) in (select p.sku from o_product p where p.id = ? )
... into this invalid SQL in my case:
select t0.id as c0, ... t0.location_id as c8
from myRecordClass t0
where (t0.location_id) in (
select t0.id
from t0.location_id t0 # should be: from location t0
where t0.customer_id = ?
) and t0.creation > ?
order by t0.creation desc
The workaround:
Use the RawSql approach like in https://stackoverflow.com/a/27431625/190599 - example here:
String sql = "select b.id, b.location_id ... " +
"from myRecordClass b " +
"where location_id in (" +
"select id " +
"from location " +
"where customer_id = " + user.getCustomer().getId() +
") " +
"order by creation desc limit 10";
RawSql rawSql = RawSqlBuilder
.parse(sql)
.columnMapping("b.id", "id")
.columnMapping("b.location_id", "location.id")
....
.create();
Query<MyRecordClass> query = Ebean.find(MyRecordClass.class);
query.setRawSql(rawSql);
final List<MyRecordClass> list = query.findList();
I hardly believe that RawSql is fastest way to achieve this kind of query, it allows you to return list of mapped objects.
It's also possible to use SqlQuery (described in Reference guide (PDF)) to fetch a list of SqlRows - so you can find required data without any mapping at all.

SQL Retrieving values from a statement with multiple selects

I have this SQL:
SELECT count (1) FROM users AS total_drafts WHERE version_replace = #sid
SELECT count (1) AS unpublished_drafts FROM users WHERE version_replace = #sid AND moderated = 0
SELECT * FROM users WHERE id = #sid ORDER By ID DESC
Which appears to be correct. However I'm having difficulty extracting the fields from the results. In vb.net I am using this code fragment:
While r.Read()
Dim o_email As String = CStr(r("email"))
Dim o_first_name As String = CStr(r("first_name"))
Dim o_last_name As String = CStr(r("last_name"))
Which is causing this error: System.IndexOutOfRangeException: email
I have checked the sql is being exucuted correctly. The sql I've posted is simply replacing a simpler statement which was feeding into the code fragment perfectly.
Why is this and how do I correct it?
the correct way:
While r.Read()
total_drafts = CInt(r("total_drafts"))
End While
r.NextResult()
While r.Read()
unpublished_drafts = CInt(r("unpublished_drafts"))
End While
error_status.Text = total_drafts & " " & unpublished_drafts
r.NextResult()
While r.Read()
Dim o_email As String = CStr(r("email"))
Dim o_first_name As String = CStr(r("first_name"))
Dim o_last_name As String = CStr(r("last_name"))
EDIT: r.NextResult() instead of r.ReadNext(), r.ReadNext() is for a DataTableReader
Assuming you are calling the whole sql statement in one go, the problem is that r.Read() will use the first datatable that is returned for the first statement(SELECT count (1) FROM users AS total_drafts WHERE version_replace = #sid ), which does not contain the email etc. fields.
You have to call r.NextResult() twice, this will move the datareader to the 3rd dataset that will contain the data from SELECT * FROM users WHERE id = #sid ORDER By ID DESC
You're returning three datasets. If "r" is a DataReader (unclear from your question) then you need to call;
r.NextResult
between your lines of code, like this;
While r.Read()
Dim o_email As String = CStr(r("email"))
r.NextResult()
Dim o_first_name As String = CStr(r("first_name"))
r.NextResult()
Dim o_last_name As String = CStr(r("last_name"))
One other possible explanation (again, unclear) is that you messed up your first column name ("email"), this would also give an out of range exception.
As far as I can understand you're trying to execute multiple statements, right?
You should separate your SQL statements with a semicolon and change the reader when you've finished with the previous one.
UPDATE:
I usually use stored procedures and return parameters for counters.
Something like this:
CREATE PROCEDURE usp_GetUsers (#sid INT, #unpublished INT OUTPUT)
AS
BEGIN
DECLARE #total_drafts INT
DECLARE #unpublished_drafts INT;
SELECT #total_drafts = count (1) FROM users WHERE version_replace = #sid
SELECT #unpublished_drafts = count (1) FROM users WHERE version_replace = #sid AND moderated = 0
SELECT * FROM users WHERE id = #sid ORDER By ID DESC
RETURN(#total_drafts)
END