I'm trying to run use rawquery to run a query with an alias on the primary key to make it _id so that I can use the SimpleCursorAdapter, this is what I have:
String sel = DatabaseListDB.COLUMN_DATABASE_NAME;
Cursor results = db.rawQuery("SELECT ? as _id FROM DatabaseList",
new String[] {sel});
In my SqlLiteHelperClass
public static final String COLUMN_DATABASE_NAME = "databaseName";
is the column name I want and my primary key. The problem is when I run this query the results come up with 'databaseName' as the values in the table instead of the actual values.
I can run the query as
Cursor results = db.rawQuery("SELECT databaseName as _id FROM DatabaseList",
null);
and it works fine and I have no idea why I cant use the selectionargs properly. Can anyone help me fix this?
? is supposed to use for WHERE arguments. In your case, you should simply alter your query as:
Cursor results = db.rawQuery(String.format("SELECT %s as _id FROM DatabaseList", sel));
From developer.android.com, you only can put "?" on where clause, not for columns you want to query:
selectionArgs: You may include ?s in where clause in the query, which will be replaced by the values from selectionArgs. The values will be bound as Strings.
Related
Postgres query:
select t
from TableName t
where t.isActive=true
order by t.extcol->'desc'
This work's fine.
Need help with HQL query which will do the same job.
String query = "select t from TableName t where t.isActive=true order by t.extcol->'desc'"
newList = TableNameModel.executeQuery(query);
Method threw 'java.lang.IllegalArgumentException' exception.
context: there is a table TableName where one column is extcol which contains object. Need to sort TableName based on a property desc which present in extcol json object.
For HQL you have the wrong syntax for sorting.
It should be order by t.extcol desc without the arrow and quotes.
see https://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-ordering
I am new in Java. Now I am trying to create a dynamic SQL table in a SQL Server Database from java. I have the table Name in a string, the column names in a ArrayList, and put the same type and length for all columns that I want. My code look like this, but when I run It I obtain this error, I don't know why, because the "query" variable is printing a "correct" Query. I test it writing a static tableName and tColumnNames and worked fine...If someone can help me to resolve it, I really will appreciate it. Thanks
private void createNewTable( String tableName, List<String> newTableColumns) throws SQLException {
//ArrayList to string separated by comma
String tColumNames = String.join(",",newTableColumns );
Connection connection = dataSource.getConnection();
Statement stmt = connection.createStatement();
String query = "CREATE TABLE "+tableName+"( "+tColumNames+" );";
System.out.println("Consulta"+query);
stmt.executeUpdate(query);
stmt.close();
}
"query" is printing this:
CREATE TABLE Courses(Subject ID VARCHAR(200),Date*
VARCHAR(200),Effective Date* VARCHAR(200) );
And it is the error
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near
'VARCHAR'. at
com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:217)
at
com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1655)
at
com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteStatement(SQLServerStatement.java:885)
at
com.microsoft.sqlserver.jdbc.SQLServerStatement$StmtExecCmd.doExecute(SQLServerStatement.java:778)
at
com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7505)
at
com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2445)
Your Java looks ok but there are syntax errors in your SQL. Do you have control of the code that generates the value for newTableColumns? That is where your problem is. Your statement should read something more like this:
CREATE TABLE Courses([Subject ID] VARCHAR(200), [Date*] VARCHAR(200), [Effective Date*] VARCHAR(200) );
If you have spaces or other T-SQL reserved characters or keywords you need to enclose them in [].
If you don't have control of the value of newTableColumns then you will need to parse that string to format it accordingly before or while you generate your SQL statement.
I generate the SQL template like this with jOOQ 3.11.11.
DSLContext context = new DefaultDSLContext(conf);
Query query = context.select()
.from("table1")
.where(DSL.field("report_date").eq(DSL.param("bizdate")))
.orderBy(DSL.param("sort"));
String sqlTemp = context.renderNamedParams(query);
SQL template:
select *
from table1
where report_date = :bizdate
order by :sort
The SQL template is stored and the params are decided at realtime query condition.
ResultQuery resultQuery = context.resultQuery(sqlTemp, DSL.param("bizdate", "20190801"), DSL.param("sort", "id desc"));
The realtime SQL:
select *
from table1
where report_date = '20190801'
order by 'id desc'
There is something wrong with the order by clause.
So. How to replace the order by param sort with "id desc" or "name asc" and eliminate the quotes?
DSL.param() creates a bind variable, which is generated as ? in SQL, or :bizdate if you choose to use named parameters, or '20190801' if you choose to inline the bind variables. More about bind variables can be seen here.
You cannot use DSL.param() to generate column references or keywords. A column expression (e.g. a reference) is described in the jOOQ expression tree by the Field type. Keywords are described by the Keyword type, but you probably do not want to go this low level. Instead you want to handle some of the logic in your query expression. For example:
String sortField = "id";
SortOrder sortOrder = SortOrder.ASC;
Query query = context.select()
.from("table1")
.where(DSL.field("report_date").eq(DSL.param("bizdate")))
.orderBy(DSL.field(sortField).sort(sortOrder));
The mistake you're making is to think that you can use a single SQL template for all sorts of different dynamic SQL queries, but what if you're dynamically adding another predicate? Or another join? Or another column? You'd have to build a different jOOQ expression tree anyway. Just like here. You could store two SQL strings (one for each sort order), and repeat that for each sort column.
But, instead of pre-generating a single SQL string, I recommend you extract a function that takes the input parameters and generates the query every time afresh, e.g.:
ResultQuery<?> query(String bizDate, Field<?> sortField, SortOrder sortOrder) {
return context.selectFrom("table1")
.where(field("report_date").eq(bizDate))
.orderBy(sortField.sort(sortOrder));
}
Here is some further reading about using jOOQ for dynamic SQL:
https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql
https://blog.jooq.org/2017/01/16/a-functional-programming-approach-to-dynamic-sql-with-jooq
I need to know the list of the column and values from the update sql using java. Code is to read a update query and take backup of the actual column values before executing the update sql. For this is need to know the column names. Please advise!
sql = update testenv.employee set gender = '2',StudentInd = '112233' where empID in (987987);
String criteriaQuery = resultset.getString("query"); // this is the update statement which is not constant and varies everytime.
String schema = StringUtils.substringBetween(criteriaQuery.toUpperCase(), "UPDATE ", ".").trim();
String table = StringUtils.substringBetween(criteriaQuery.toUpperCase(), ".", "SET").trim();
String columnName = StringUtils.substringBetween(criteriaQuery.toUpperCase(), "SET", "=").trim();
But columnName will not get the correct columns. Need to optimise the code such that i can get the entire column names from the update query.
If you're using JDBC, you can use the following:
ResultSetMetaData md = rs.getMetaData();
after getting the result set of your select statement.
http://www.roseindia.net/jdbc/jdbc-mysql/DiscriptionTable.shtml
Provides a clear example, the same applies for SQLServer databases and Oracle.
I am trying to build a dynamic sql query in java (shown below)
sqlStr = "Select * " +
"from " + tableName
if(tableName!=null){
if(tableName.equals("Table1"){
sqlStr = sqlStr.concat("order by city desc");
}else if(tableName.equals("Table2"){
sqlStr = sqlStr.concat("order by country desc");
}else if(tableName.equals("Table3"){
sqlStr = sqlStr.concat("order by price desc");
}
}
Now what i would like to do is to add a final 'else' statement which would order the query based on whether the table contains a column named 'custID'. There will be several tables with that column so i want to sort the ones that have that column by custID. (Rather than having hundreds of additional if statements for each table that does have that column name.) Is this possible? i have seen people using the 'decode' function but i cant work out how to use it here.
Use DatabaseMetaData to get the table information.
You can use the getTablexxx() and getColumnxx() methods to get the table information.
Connection conn = DriverManager.getConnection(.....);
DatabaseMetaData dbmd = conn.getMetaData();
dbmd.getxxxx();
Note: you forgot space in your code before ORDER BY clause.
If you are happy with hardcoding things, a way to avoid multiple conditionals would be to store a list of all the tables that include custID.
private final static String tablesWithCustID = "/TableX/TableY/TableZ/";
...
if (tablesWithCustID.contains( tableName )) {
sqlStr = sqlStr.concat("order by custID")
}
You could use a List instead of a simple delimited string if you like.
Perhaps better, you could store a map with table names as the key, and the sort string as the value. Load it up once, then you don't need any conditional at all.
The most straight-forward way to do it is to read the column definitions from USER_TAB_COLUMNS or ALL_TAB_COLUMNS and check for the existence of a custID column. Without crazy PL/SQL tricks, you won't be able to solve this in SQL alone.
BTW, there is a " " missing between tableName and the order by clauses.
I understand that you're looking for a solution that can do this in one query, i.e. without running a separate metadata query beforehand.
Unfortunately, this won't be possible. The decode function can do some dynamic things with column values, but not with column name. And you're looking for a solution dynamically derive the column name.
An alternative might be to just add ORDER BY 1, 2. This is an old syntax that means order by the first and than by the second column. It might be a good solution if the custID column is the first column. Otherwise it at least gives you some sorting.
How about ArrayList.contains()?
You can create a list of tables which have that column, and just check for tables.contains(tablename) in the final if condition.