i am migrating from ms access database to mysql database with java frontend so that my application can be used in linux as well .
in ms access here's what i would do
go to create query . write a select statement . call give the name of the query as query1.
when double clicking on query1 you would get the result of select statement in a tabular form.
next i would write a query2 which is also a select query. this query would be fetching data not from a table but query1 e.g select a,b from query1;
now i am on a mysql database using java
what would be the java statement for select a,b from query1 ?
what i mean to say is that i would connect to mysql using jdbc.
have query1 like this
string query1 = " select * from users " ;
then execute query using executeQuery(query1)
but i dont think i can do something like this.
string query2 = " select a,b from query1 " ;
and then executeQuery(query2)
so what is the way out ?
I ran into the exact same problems when I went from using MS Access to using a lot of SQL queries against a MySQL DB.
There are two ways I would approach this:
VIEWS:
Views are a great way to emulate a lot of the functionality you found in Access. One of the things I really liked about Access was the ability to separate my SQL into smaller queries and then re-use those queries in other queries. Views allow you to do essentially the same thing in that you define a query in a View and then you can write another query or View against that original View.
In my experience, however, Views tend to be really slow, especially when referencing calculated columns. With MySQL, I very rarely use Views (though perhaps others have found for efficient ways of implementing them).
SUBQUERIES (NESTED QUERIES)
As others have mentioned, subqueries are a great way to write multiple queries within one query. With a subquery, instead of putting the query name (as in Access) or View name (as explained above) within the SELECT portion of your code, you simply paste the entire SQL statement of the subquery.
You might write code like this to find only the 2009 sales and salesperson name for customers in a database:
SELECT
customer.Name,
customer.AccountNumber,
customer.SalespersonName,
ch.`2009 Sales`
FROM
customer
Left Join (
SELECT
customerhistory.AccountNumber,
SUM ( CASE WHEN customerhistory.`Year` = 2009
THEN customerhistory.`Sales`
ELSE 0
END
) AS `2009 Sales`
FROM
customerhistory
GROUP BY
customerhistory.AccountNumber
) ch ON customer.AccountNumber = ch.AccountNumber
In my work, I tend to use mostly subqueries since I find they run a lot faster than views, but your experience may vary.
You can do this all in MySQL. The query would look like
SELECT * FROM (
SELECT * FROM users
) query1;
You can either do nested queries (subqueries) like #muffinista suggested.
But i think you are looking for Views: http://dev.mysql.com/doc/refman/5.0/en/create-view.html.
In short, a view is a "pseudo table" that is a result of a query.
you can
create view q1 as
select * from table1 where f1>1
select * from q1 where f2<100
select * from table2 where user_id in (select user_id from users)
Related
I have a following problem. In application, which I am developing, we use Hibernate and every query is written with Criteria API. Now, in some places, we want to add possibility for user to write some SQL code which will be used as part of where clause in a query. So basically, user can filter data displayed to him from database in his own way.
For a few days now, I am trying to find a way to modify our previous queries to acquire result described above. Here is what I know:
It looks like you cannot combine Criteria API with native SQL. You can either write whole query in SQL or use only criteria API. Is that right?
I am asking this question because it would be the easiest solution, just to use this SQL code as another predicate in where clause in our query. But I don't think it's possbile on this level.
I know on which table user wants to filter data. So I could just execute native SQL query and use result list as a parameter to IN clause in criteria query. But I don't know if it is efficient with many records in a result list.
So if I cannot do it on criteria API level, I thought that maybe I could somehow influence the SQL generetion process and put my SQL in a proper place but it seems to be impossible.
So my real question is: is it somehow possible to have access to SQL code of the query, after SQL generation phase but before actual execution of query? Just to manipulate with it manually? Can it be done safely and as far as possible simply?
Or maybe just try to parse this SQL written by user and use it in criteria query?
Changing existing criteria queries into native SQL queries is rather out of discussion.
Yes, you can get the SQL from the Hibernate criteria using the org.hibernate.loader.criteria.CriteriaQueryTranslator class.
This will allow you to append the additional SQL clause(s) to the end and execute it as a native SQL:
CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteria, "myEntityName", CriteriaQueryTranslator.ROOT_SQL_ALIAS);
String select = translator.getSelect();
String whereClause = translator.getWhereCondition();
Personally though, if faced with this requirement I would shy away from accepting SQL from the end-user and give them a user interface to populate some type of filter object. This can then be converted into HQL criterion, which is much safer and doesn't tie your code as tightly to the database implementation.
Edit based on comments
Example of extracting SQL from a JPA query implemented with Hibernate:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> q = builder.createQuery(MyEntity.class);
Root<MyEntity> entity = q.from(MyEntity.class);
q.select(entity).orderBy(builder.desc(entity.get("lastModified")));
TypedQuery<MyEntity> query = entityManager.createQuery(q);
String sql = query.unwrap(org.hibernate.Query.class).getQueryString();
criteria.add(Restrictions.sqlRestriction(" AND ID in (1,2,3)" ));
I'm working on a feature which allow some users to define their own SQL queries and run them on the database.
Basically a query could look like this:
1. SELECT first_name, last_name FROM user;
2. SELECT first_name, last_name, id, address, email FROM user.
As you can see there may be a different number of columns in the result table.
Is there a way to handle this in Hibernate?
For instance, the basic usage displayed below does not help me in any way because I cannot be sure that each result row has at least 2 columns.
Query query = session.getSession().createSQLQuery(queryStr);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
while (results.next()) {
data.put("firstName", String.valueOf(results.get(0)));
data.put("lastName", String.valueOf(results.get(1)));
}
Furthermore, I don't think I can use the select new map because the users have to run native MySQL queries.
Is there any solution to this?
Thanks in advance for your time and suggestions!
First of all, I do not think that it is a good idea to expose an interface that allows SQL input to users.
Anyway, in your case you could program the SQL result set extraction yourself. There is no need for object relational mapping, if you do not map into objects. You could then go and just check for the existence of the columns and map them right away into your data structure. Nice way to learn plain JDBC. Just for the case you use Hibernate for other issues in your application, you can even mix the approaches.
Iam trying to implement memcache in my web application and just wanted to get suggestions that whether what iam doing is right in terms of design.
I have a class SimpleDataAccessor which run all my insert, update and select sql queries. So any query that has to be performed is executed inside the method of this class.
So inside the method where I have my select query implementation i have a method which stores the resultset in memcache like this.
storeinMC(resultset.getJSON(),sqlquery);
the sqlquery here is my key.
Also before running the selectquery i check in memcache that whether I have a resultset already for that query.
if((String res=getRSFromMC(sqlquery)==null)
So i've tried to keep it plain and simple.
Do you see any issues with this.?
As rai.skumar rightfully pointed out your SQL statements could be constructed differently (e.g. WHERE clause could contain same conditions in diff order, etc.)
So to overcome above mentioned issues, you need to parse your SQL and get all the relevant pieces from it. Then you can combine these pieces into a cache key.
You can take a look at SQL parsers: ZQL, JSqlParser, General SQL Parser for Java that return you java classes out of your SQL.
Another option would be to use JPA instead of straight JDBC. For example Hibernate has great JPA support and fully capable of caching your queries.
If you feel closer to JDBC you could use MyBatis that has very JDBC like syntax and caching support.
Consider below queries:
String k1 = "Select * from table"; //Query1
String k2 = "Select * from TABLE"; // Query2 ; notice TABLE is in caps
Both of above SQL queries are same and will fetch same data. But if above queries are used as keys in Memchached they will get stored at different places ( as k1.equals(k2) will return false).
Also if somehow you can ensure that there are no typos or extra spaces, it won't be very efficient as keys/queries could be very big.
I have a table named "preference" which includes more than 100 columns in oracle,I wrote a little bit complicated SQL which need use keyword UNION/INTERSECT/MINUS to do a query.
Take a simple example:
select a.* from preference a where a.id = ? union
select a.* from preference a where a.id = ?
The business care have been changed due to unlimited length string storage on demand. one column need to be re-defined to Clob type. Oracle don't allow union on the clob type, so ideally the a.* cannot be used here.
I changed SQL to like below:
select a.a,a.b,a.c... from preference a where a.id = ? union
select a.a,a.b,a.c... from preference a where a.id = ?
It lists all columns except clob and then I have to do another selection to append the Clob value together. Is that a good idea?
The Another issue brought from above case is that: as I mentioned this table has large columns, list all columns in sql it make SQL much longer. Is there expression I can select all columns but getting rid of specific one?
Oracle when delaing with log does not allow union/minus but allows union all, may be you can rewrite your query using union all and use a select . in the select clause you can issue a select a. or list every column.
After reading your question my main concern is memory usage on Java, are you using an orm to load the data? or are you using the jdbc api?
If you are loading all the clobs into some strings you could end with an OutOfMemoryError. My advice is to load the clob only for rows you need to show to the user (or for the rows where the clob filed has to be processed).
Can you give more insight about your application (the numer fo rows it has to process) and your data (epsecially the clob size)?
I would like to do something in Java (using iBatis, JDBC, etc., really in SQL) like:
SELECT SUM(rowName) FROM myTable WHERE id = [myArrayOfIds]
Where myArrayOfIds can be almost any length. Now I know you can do:
SELECT SUM(rowName) FROM myTable WHERE id IN (x, y, z)
but what happens for longer lists? For example my list could be as little as a few items to hundreds or more items. How can I do this?
I think it depends on your flavour of SQL. For instance, Oracle does not allow more than 1000 values in an IN() list. Other flavours may vary.
one alternative would be to insert those ids to a table, then do a join
SELECT SUM(rowName) FROM myTable ta inner join tempTable tb on ta.id = tb.id
Oracle definitely allows more than 1000 items in the IN clause. It's your persistence tool that is limiting this. iBatis or Hibernate, whatever. Use Oracle Sqlplus and you'll see this is not an Oracle limit.
Suggestion from BlackTigerX would work, or you could call the query multiple times, passing 1000 items at a time and aggregating the results. Either way, you're just working around your persistence tool limitation.