Handle null values within SQL IN clause - sql

I have following sql query in my hbm file. The SCHEMA, A and B are schema and two tables.
select
*
from SCHEMA.A os
inner join SCHEMA.B o
on o.ORGANIZATION_ID = os.ORGANIZATION_ID
where
case
when (:pass = 'N' and os.ORG_ID in (:orgIdList)) then 1
when (:pass = 'Y') then 1
end = 1
and (os.ORG_SYNONYM like :orgSynonym or :orgSynonym is null)
This is a pretty simple query. I had to use the case - when to handle the null value of "orgIdList" parameter(when null is passed to sql IN it gives error). Below is the relevant java code which sets the parameter.
if (_orgSynonym.getOrgIdList().isEmpty()) {
query.setString("orgIdList", "pass");
query.setString("pass", "Y");
} else {
query.setString("pass", "N");
query.setParameterList("orgIdList", _orgSynonym.getOrgIdList());
}
This works and give me the expected output. But I would like to know if there is a better way to handle this situation(orgIdList sometimes become null).

There must be at least one element in the comma separated list that defines the set of values for the IN expression.
In other words, regardless of Hibernate's ability to parse the query and to pass an IN(), regardless of the support of this syntax by particular databases (PosgreSQL doesn't according to the Jira issue), Best practice is use a dynamic query here if you want your code to be portable (and I usually prefer to use the Criteria API for dynamic queries).
If not need some other work around like what you have done.
or wrap the list from custom list et.

Related

Want to create user-accessible form in Axapta that uses SQL with a substring function

I have some sqlserver sql that due to data can't be modified, which I currently run from Sqlserver. It uses a substring function. I want to stop running it from Sqlserver and create a user-accessible form in which the user enters a date and the script goes off and does it's thing and returns row data to the user.
Not overly familar with X++. I've looked at reports, querys, jobs, statement classes, not sure what's the correct path.
Below is the sql code.
'
select a.description,b.itemid, c.phantom,a.createddatetime,a.createdby
from sysdatabaselog A
inner join
bomversion B
on substring(a.description,1,11) = b.bomid
inner join
inventtable C
on b.itemid = c.itemid
where (table_ = 18 and logtype=1)
and a.CREATEDDATETIME > '2018-03-01' <-------- this would be user-supplied on the form
and c.phantom=1
'
What you're trying to accomplish is actually pretty high-level in AX and requires a several different dev techniques to accomplish it. I'm not going to do the entire thing for you, but I'll get you started and tell you what you need to do. These screenshots are from AX2012.
To accomplish the SUBSTRING() you need an AX View + String computed column.
For your view, you'll want an AX Query object to contain your joins OR you can just do a simple view on the BOMVersion table and then work against that.
Here's an example View and String computed column and the method for the computed column. I just used SalesTable and SalesId as the sample.
public static server str compSubStrSalesName()
{
str result;
result = strFmt("SUBSTRING(%1, 1, 5)",
SysComputedColumn::returnField(identifierStr(SubStringExample), // The name of your view
identifierStr(SalesTable_1), // The name of your view's datasource
identifierStr(SalesId) // The name of the field
)
);
return result;
}

Is it possible to pass and use sql inside a sql parameter?

I'm working with a query that is used by multiple services but the number of results returned are different based on filtering.
To avoid copying and pasting the query, I was wondering if it was possible to pass in piece of sql into a sql parameter and it would work? I'm also open to alternative solutions.
EXAMPLE:
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("filter", "and color = blue");
namedParameterJdbcTemplate.query(“select * from foo where name = 'Joe' :filter”, parameters, new urobjRowMapper());
It is very dangerous and fragile to let callers pass SQL to your program, because it opens you up to SQL injection - the very problem the parameters are there to prevent.
A better approach is to pre-code the filters in your query, and protect them by a special "selector" parameter:
SELECT *
FROM foo
WHERE name='Joe' AND
(
(:qselect = 1 AND color='blue')
OR (:qselect = 2 AND startYear = 2021)
OR (:qselect = 3 AND ...)
)

Using linQ to perform a simple select where

I am using VS2013 with SQL server 2012, VB.net. I am developing a web application.
Let me say before I ask the question that this will probably be extremely simple for this board but I have not been able to find this through googling.
I have an SQL table that holds some data, two columns (settingName (nvarchar) and settingValue (float)). I want to do the following but using LinQ.
SELECT Settingvalue
FROM Settings
WHERE settingName = 'Name1'
I have the following so far in VB.
Dim db As New GMConnectionDataContext
Dim result = From a In db.Settings
Where a.SettingName = "Name1"
Select a.SettingValue
txtEgdon.Text = result
This doesn't work as result is a double but if I add .tostring to result then the output in the text box is the full linq query not the result I am looing for.
I just need to understand this simple query so I can build on it but I just cant get it and any help offered would be great.
This is because your result is an IQueryable and not a single value(even if you expect it to be). This is also why ToString will get you the SQL that will be run against your DB.
You need to get either the First or if you are really sure this would be a single value get Single. The OrDefaults are used in the case that no value is returned so the result will be null.
A Few options:
// You expect 1 to many results and get the first
txtEgdon.Text = result.First().ToString()
// You expect 0 to many results and get the first or null in case of zero results
txtEgdon.Text = result.FirstOrDefault().ToString()
// You expect exactly 1 result and get it (you will get an exception if no results are returned)
txtEgdon.Text = result.Single().ToString()
// You expect exactly 0 or 1 results and get null or the result
txtEgdon.Text = result.SingleOrDefault().ToString()
I would prefer the FirstOrDefault()

How to Write a Where Clause to Handle Either a Specific Value or Any Value

I have a report with a table in Rails where users can optionally set filters like selecting a location or picking a range of dates and update the table via an ajax request.
Can I write this where clause so that it any date/blanks or all locations?
#orders = Order.where('created_at <= ? AND ? <= created_at AND location_id = ?', date_order_start, date_order_end, loc_filter)
The query above fails on blanks (e.g., "") and if I put nils they translate to nulls in the SQL.
To solve this problem right now I have a bunch of conditional statements that check whether value is present in the ajax request and then creates a different where clause depending on the case. My current conditionals are unwieldy, error prone and not scalable.
Searches on things like "wildcard sql" end up leading me to text searches (i.e., %) which I don't think fits in this case.
I am running on Rails 3.2 with postgresql.
I sometimes use an array of query statements and arguments like this:
queries = []
args = []
if some_condition
queries.push("created_at <= ?")
args.push(whatever_date)
end
if another_condition
queries.push("created_at >= ?")
args.push(another_date)
end
#order = Order.where(queries.join(" AND "), *args)

How to select if a row exists in HQL

EDIT: Specifically talking about querying against no table. Yes I can use exists, but I'd have to do
select case when exists (blah) then 1 else 0 end as conditionTrue
from ARealTableReturningMultipleRows
In T-SQL I can do:
select case when exists(blah) then 1 else 0 end as conditionTrue
In Oracle I can do:
select case when exists(blah) then 1 else 0 end as conditionTrue from DUAL
How can I achieve the same thing in HQL?
select count() seems like the second-best alternative, but I don't want to have to process every row in the table if I don't need to.
Short answer: I believe it's NOT possible.
My reasoning:
According to Where can I find a list of all HQL keywords? Hibernate project doesn't publish HQL grammar on their website, it's available in the Hibernate full distribution as a .g ANTLR file though.
I don't have much experience with .g files from ANTLR, but you can find this in the file (hibernate-distribution-3.6.1.Final/project/core/src/main/antlr/hql.g):
selectFrom!
: (s:selectClause)? (f:fromClause)? {
// If there was no FROM clause and this is a filter query, create a from clause. Otherwise, throw
// an exception because non-filter queries must have a FROM clause.
if (#f == null) {
if (filter) {
#f = #([FROM,"{filter-implied FROM}"]);
}
else
throw new SemanticException("FROM expected (non-filter queries must contain a FROM clause)");
}
which clearly states there are some HQL queries having no FROM clause, but that's acceptable if that's a filter query. Now again, I am not an expert in HQL/Hibernate, but I believe a filter query is not a full query but something you define using session.createFilter (see How do I turn item ordering HQL into a filter query?), so that makes me think there's no way to omit the FROM clause.
I'm use fake table with one row for example MyDual.
select case when exists(blah) then 1 else 0 end as conditionTrue from MyDual
According to http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-expressions it looks like they support both case and exists statements.