I'm looking for difference between ax query and select (or while select)
In this example i don't see what's i can not do with statement select : the example of ax query in msdn
I think I misunderstood the syntax of ax query ranges :'(
A (while) select is a 'one use' statement, ie, you put it inline in your code and it is used only there.
A query can be setup to require parameters and can be used multiple times throughout your class or saved into the AOT for use in any class.
Generally I only use select statements for simple queries where its not worth the effort to create a query, for anything more complex I use queries.
Related
In AX programming best practice, which is the best way:
using a Query created from the AOT,
using a select statement with X++ code,
using a query created with X++ code the Query classe ...
And when to use each one of them?
First off, AX always uses queries internally, X++ selects are translated to query constructions calls, which are executed at run time. The query is translated to SQL at runtime on the the first queryRun.next() or datasource.executeQuery(). There is thus no performance difference using one or the other.
Forms also use queries, most often it is automatically constructed for you, because property AutoQuery has a Yes default value. You can use a X++ select in the executeQuery method, but I would consider that bad practice, as the user will have no filter or sorting options available. Always use queries in forms, prefer to use the auto queries. Add ranges or sorting in the init method using this.queryBuildDatasource() if needed. The exception being listpages which always use an AOT query.
In RunBase classes prefer to use queries, as the user will have the option to change the query. You may of cause use simple X++ select in the inner loop, but consider to include it in the prebuilt query, if possible.
Otherwise, your primary goal as a programmer (besides solving the problem) is to minimize the number of code lines.
Queries defined in the AOT start out with zero code lines, which count in their favor. Thus, if there are serveral statically defined ranges, links, or complex joins, use AOT queries. You cannot beat:
QueryRun qr = new QueryRun(queryStr(MyQuery))
qr.query().dataSourceTable(tableNum(MyTable)).findRange(fieldNum(MyTable,MyField)).value('myValue');
With:
Query q = new Query();
QueryRun qr = new QueryRun(q);
QueryBuildDataSource ds = q.addDataSource(tableNum(MyTable));
QueryBuildRange qbr = ds.addRange(fieldNum(MyTable,MyField));
qbr.value('myValue');
qbr.locked(true);
Thus in the static case prefer to use AOT queries, then change the query at runtime if needed. On the flip side, if your table is only known at runtime, you cannot use AOT queries, nor X++ selects, and you will need to build your query at runtime. The table browser is a good example of that.
What is left for X++?
Simple selects with small where clauses and with simple or no joins.
Cases where you cannot use queries (yet), delete_from, update_recordset and insert_recordset comes to mind.
Avoiding external dependencies (like AOT queries) may sometimes be more important.
Code readability of X++ queries is better than query construction.
The main techniques for selecting records in the database are as follows:
The select statement
A query
The techniques are essentially the same. They both deliver a set of records from the database in a table variable that can be accessed.
Use the select statement when:
The selection criteria are complex.
You are selecting a set of records from X++. The user is not going to change the selection criteria.
Use a query when:
The user can choose which records are selected.
The user can change the range of records to be selected.
The selection criteria are not more complex than the query can accommodate.
When you use queries, develop them in the Application Object Tree (AOT) or build them from scratch in your code. In both situations, the query can be modified in the code. A query built from scratch in code can be saved so that it occurs in the AOT. However, this should usually be avoided.
Build a query in the AOT when:
A specific query definition is being used in many places. (The query in the AOT can be reused.)
The query must contain code.
The query definition is more complex. The AOT provides a visual representation of the query.
I found a query like select cast (:v as customtabletype) from dual.
Not able to understand what is the meaning of above line, written as dynamic query.
:<variablename>, in your case ":v", is what is known as a bind variable.
Essentially, this is a placeholder which is replaced with another value as the SQL statement is executed.
For more in-depth reading it is probably worth looking for bind variables in the Oracle documentation, as there is a lot of information available on why they're used and their benefits.
I am working on a report, and for my data set i need to use an or statement. in SQL my query would look like:
SELECT recId, etc... FROM CustTrans
WHERE (CustTrans.Closed IS NULL AND CustTrans.Invoice IS NULL)
OR (CustTrans.Invoice IS NOT NULL)
I would translate this then into range like the following (stuck on the RecId field)
Value:
((CustTrans.Invoice == ‘’) && (CustTrans.Closed == ‘’) || (CustTrans.Invoice != ‘’))
I have found numerous places explaining that this is the proper syntax, although all of them are using the programmatic method of creating a query. I need to keep mine in the AOT so the customer can modify it later on if they want, and every combination of quotes, parens, and order still does not work. Sometimes AX will accept my range value string, but it doesn't do anything, and sometimes it will give me a random syntax error.
Is there a way to accomplish what I'm looking to do? have I missed some syntax, or does AX really not let you use OR on a query without a union and another view?
Thanks!
You can create a Query in the AOT and then over-ride the init method for the Query. Where you can put these complex SQL statements and get your work done.
The following query takes 5 seconds to execute:
SELECT DISTINCT(Product.Name) FROM Product WHERE (0=1 OR Product.Number="prod11");
While the following takes ONLY 15 milliseconds:
SELECT DISTINCT(Product.Name) FROM Product WHERE (Product.Number="prod11");
Interestingly the following also takes only 15 milliseconds:
SELECT DISTINCT(Product.Name) FROM Product WHERE (1=1 AND Product.Number="prod11");
The query plan shows that the first query uses a full table scan (for some unknown reason), while the second and third queries use an index (as expected).
For some reason it looks like Sqlite optimizes the "1=1 AND ..." but it doesn't optimize "0=1 OR ...".
What can I do to make Sqlite use the index for the first query as well?
The queries are built by NHibernate so it's kind of hard to change them...
Sqlite version is the latest for Windows.
SQLite's query optimizer is rather simple and does not support OR expressions very well.
For some reason, it can optimize this query if it can use a covering index, so try this:
CREATE INDEX TakeThatNHibernate ON Product(Number, Name)
1=1and 1=0 are SQL expressions used in some parts of the NHibernate framework to denote empty statements that won't alter the logic of the sql query. A Conjunction with no subcriterias generates an 1=1 expression, A Disjunction with no subcriterias generates an 1=0 expression. An In() generates an 1=0 expression if no values are provided.
To avoid such optimization, you could change the code that is creating those empty expressions and only use the criterions that have at least one subcriteria.
I am thinking of using Simple.Data Micro-ORM for my ASP.NET 4.5 website. However, there is something that I need to know before deciding whether to use it or not.
Let's take the following Join query for example:
var albums = db.Albums.FindAllByGenreId(1)
.Select(
db.Albums.Title,
db.Albums.Genre.Name);
This query will be translated to:
select
[dbo].[Albums].[Title],
[dbo].[Genres].[Name]
from [dbo].[Albums]
LEFT JOIN [dbo].[Genres] ON ([dbo].[Genres].[GenreId] = [dbo].[Albums].[GenreId])
WHERE [dbo].[Albums].[GenreId] = #p1
#p1 (Int32) = 1
Let's assume that the 'Genres' table is a a table with thousands or even millions of rows. I think that it might be very inefficient to filter the data after the JOIN has taken place, which is what this query translated for in Simple.Date.
Would it be better to filter the data firs in the Generes table, which means create make a SELECT statement first and make the JOIN with that filtered table?
Wouldn't it be better to filter the data ahead of time?
Furthermore, is there an option to make that type of complex (JOIN on a filtered table) query using Simple.Data.
Need your answer to know if to proceed with Simple.Data, or damp it in favor of another micro-ORM.
You are confused about how SQL is interpreted and executed by the database engine. Modern databases are incredibly smart about the best way to execute queries, and the order in which instructions appear in SQL statements has nothing to do with the order in which they are executed.
Try running some queries through SQL Management Studio and looking at the Execution Plan to see how they are actually optimised and executed. Or just try the SQL you think would work better and see how it actually performs compared to what is generated by Simple.Data.
The sql that Simple.Data is generating is idomatic T-SQL, too be honest its what I would be writing if I was drafting the sql myself.
This sql allows Sql Server to optimise the execution plan which should mean the most efficient retrieval of data.
The beauty of Simple.Data is that if you have any doubts or issues with the sql it generates you can just call a stored proc:
db.ProcedureWithParameters(1, 2);