Order By in esql - messagebroker

I have an xml message like this
<Body>
<test>
<element>2</element>
<element>6</element>
<element>1</element>
</test>
</Body>
and i want to select the element with the lowest number
something like this
SET data[] = SELECT e FROM Output.Body.test.element[] AS e ORDER BY e.element;
I would have done this if the "ORDER BY" is supported in esql select but it is not, So is there any other way to do something like this?
I know the sql statements can be supported if i used PASSTHRU statement which passes the statement to the DBMS directly, but i am not using DBMS here, i am selecting from xml message.

With the following link you can write a Quick Sort procedure to order your list. Then, you just have take the first element of the list.
Source: http://www.mqseries.net/phpBB2/viewtopic.php?p=273722#27372
(I only posted a link because the procedure code is pretty huge and could be updated by his creator)

Related

Is there any way to get the syntax of an SQL statement when using SQLPlus?

I have an exam using SQLPlus and sometimes I don't remember the exact syntax of SQL statements, so I was wondering if there is any way to get some nice inline help from inside SQLPlus.
For instance, say I forgot how to use INSERT INTO, and I want some reminder like this:
INSERT INTO table-name (column-names)
VALUES (values)
Is this possible?
I tried HELP command but none of that seems to suits my needs.
I Googled it with no success.
No. SQL is a standardized language (at least ANSI SQL) and SQLPlus "just" uses that syntax, so it's not covered by internal help. Internal help lists only SQLPlus specific commands (ex. SET, CONNECT, SPOOL).
It is possible to workaround that in some way, but very limited. You can call dbms_metadata.get_ddl function for some existing object. Some of those DDLs could have statements you are intrested in. For example - you'd like to see select statement - then you could call dbms_metadata.get_ddl for some existing view:
select dbms_metadata.get_ddl('VIEW', 'USER_TABLES', 'SYS')
from dual;
Be aware - it works only for Oracle 11G and lower, in the newest one SYS objects are not accessible in that way (I'm not sure about Oracle 12.1).
The more interesting are tiggers, procedures, functions, and packages. You cannot use dbms_metadata to get DDLs of packages owned by SYS, but maybe you can connect to some sample schemas like HR (Human Resources), AD (Academic), SH (Sales History).
In HR schema there is stored procedure ADD_JOB_HISTORY, which has inside insert statement, so it looks like that:
select dbms_metadata.get_ddl('PROCEDURE', 'ADD_JOB_HISTORY')
from dual;
CREATE OR REPLACE EDITIONABLE PROCEDURE "HR"."ADD_JOB_HISTORY"
( p_emp_id job_history.employee_id%type
, p_start_date job_history.start_date%type
, p_end_date job_history.end_date%type
, p_job_id job_history.job_id%type
, p_department_id job_history.department_id%type
)
IS
BEGIN
INSERT INTO job_history (employee_id, start_date, end_date,
job_id, department_id)
VALUES(p_emp_id, p_start_date, p_end_date, p_job_id, p_department_id);
END add_job_history;
There are better ways and better tools to achieve your goal - see below.
Are you allowed to use SQL Developer instead of SQLPlus? SQL Developer has nice feature to drag-and-drop table icon into worksheet, then you will be nicely prompted to choose what kind of example statement you are looking for (SELECT, INSERT, UPDATE etc.) - after choosing one you will get sample statement.
But the best way is just open in browser Database SQL Language Reference:
https://docs.oracle.com/database/121/SQLRF/toc.htm

Edit SQL in Power Query

When I import data from Sql Server in Power Query, I can paste a query to be executed against the database. But later when I want to edit this query in Workbook Queries > Edit > Advanced Editor, I get something like this:
let
Source = Sql.Database("server", "database", [Query="select#(lf)#(tab)*#(lf)from dbo.SomeView va#(lf)join dbo.SomeTable rm#(lf)#(tab)on rm.CatId=va.CatId#(lf)where 1=1#(lf)#(tab)and Month between 1501 and 1510#(lf)#(tab)and rm.Id in (1,2,3)"])
in
Source
Please note that I'm using *, but with explicit column names this would look even worse.
I'd like to be able to see the query in a readable form, then copy it, execute in Management Studio, change something and paste back to Power Query. I know I could be using views as a source, or not using newlines and indentation, but that's not my point.
Any ideas on how to edit SQL in "normal" form? Or maybe I'm missing some hidden option.
EDIT:
In case I'm not the only person in the world having problems finding this option, it's in:
Power Query > Launch Editor > View > Query Settings > Applied Steps > Source > Gear icon
Thanks Alejandro!
If you click on the gear icon next to Source in the Query Settings pane you'll get a dialog with the SQL query in a readable form.
Here's an illustration that complements the accepted answer.

FireDAC - Show SQL after Macro Expantion

I am trying to use Macros in FireDAC to Preprocess my SQL Queries. I have a TADQuery object on a Data Module with the SQL set to something like:
Select * from MyTable
join OtherTable on MyTable.Key = OtherTable.Key
&Where
Then in my code I do this:
WhereClause = 'stuff based on my form';
Query.MacroByName('Where').AsRaw := WhereClause;
Query.Open;
This has worked great for complicated queries because it lets me make sure my fields and join conditions are correct using the SQL Property editor.
My problem is when the SQL statements ends up invalid because of my where clause. Is there any way to see the SQL after pre-processing that is going to be executed? Right now I am catching the FireDac errors and showing the SQL that is on EADDBEngineException object. However that is still showing my original SQL with the macros. If I can't get to it after the error happens is there anyway to force the Macro replacement to take place so I can look at the SQL in the debugger to help me see what is wrong.
If it matters I am connecting to a MS Access database with the goal of moving to SQL Server in the near future.
Apart from using Text property, to monitor what SQL is actually going to the database engine, consider using the "FDMonitor" FireDAC utility. According to the DokWiki pages (below):
drop a TFDMoniRemoteClientLink component on your form,
Set its Tracing property to True,
Add the MonitorBy=Xxx connection definition parameter to your existing FDConnection component. You can do this in the IDE object inspector, by selecting your FDConnection component, expanding the Params property, and setting MonitorBy to mbRemote.
Note that the TFDMoniXxxxClientLink should come before TFDConnection in the data module or form creation order, so adjust this by right clicking on the form or data module, then Creation Order, and moving the TFDMoni.. component above the FDConnection.
Also, it's helpful in the options of the TFDMoniXxxxClientLink, to disable most of the events being recorded, otherwise all the data returned is also shown in the FireDAC monitor. Expand the EventKinds property, and turn all the event kinds off, except for perhaps ekConnConnect, ekConnPrepare, and ekCmdExecute.
Then open the FireDAC Monitor from the IDE, (Tools > FireDAC Monitor). Start your app only once the monitor is running. Double click on a trace event (in the Trace Output tab), and you will see the actual SQL sent to the database in the bottom pane.
It also seems likely that adding the EventType of ekConnPrepare as mentioned above, would show you when the query's Prepare is called, but I haven't played enough with it say for sure.
Please see the following pages on the DocWiki for more information:
Overview: FDMonitor
How to: Tracing and Monitoring (FireDAC)
Other FireDAC utilities: Utilities (FireDAC)
(Just to remove this question from list of unanswered questions)
From comments:
Well, I've roughly checked what's happening there and I'm still not
sure if calling Prepare (which is useless for you as I get) is the
minimal requirement to trigger that preprocessing. Though, the
preprocessed SQL, the one which is sent to the DBMS you can access
through the Text property (quite uncommon name for such property). – TLama Feb
21 '14 at 8:18

BDE says "Field not found" but field exists

I have the following query to one of my database tables:
select count(*) as mycount
from mytable
where fieldone = :fieldone
and fieldtwo = :fieldtwo
Parameters are correctly loaded into the query (both of type String).
When I run this query outside the app (for instance, through the dbexplore) and replace the parameters with the actual values, I get the correct result. But when running it in the app, I get a Field 'fieldtwo' not found error, right on the Query.Open call.
Why would the BDE not find this field, when it actually exist?
Update: The following query, executed right after the first one (the one that fails), works fine in the app:
select *
from mytable
where fieldone = :fieldone
order by fieldone, fieldtwo
The best guess is that you have populated the field list in the query, this overrides any concept of the underlying fields that are in the query and is a cause of countless confusion.
Right click on the query, pick the fields editor clear all the values that are there and then choose 'add all fields' that should cause the missing field to appear once the query is executed.
I think it should auto-populate the fields if there are no defined fields when the query is executed, so you may not need to choose 'add all fields' after clearing the fields.
Whenever we come across a problem like this we tend to remove the query from the form and create it dynamically at run time... It depends how ingrained into the form it is...
E.g. If you have a data aware control looking at "fieldtwo" which tries to fetch some data when the underlying data set gets updated then it'll trigger an error like this, but it's more obvious when you've written code such
SomeEdit.Text = Query.FieldByName("fieldtwo").AsString;
That way it falls over on the relevant line instead of the open (triggering a related event)
Clear the query content using Query1.SQL.Clear; statement before opening it.
Other reason can be you are opening other database which may not have the specified field. Be sure that both the DatabaseName's in your app and dbexplore are same
I used to face porblems with BDE when i have SQLExplorer open and the app accesses the DB at the same time (but i had errors like ), try closing the Explorer it may help, if not i would build the SQL as text without the Parameters and try if it works then (if its possible in your situation).
I don't use parameters, so I'm just grabbing at straws here. I still use the BDE regularly, but am no expert. I find I shy away from more complex expressions (which yours is not!) because of the little "surprises" like this that the BDE throws at you.
Perhaps adding parentheses:
where (fieldone = :fieldone)
and (fieldtwo = :fieldtwo)
Or, single or double quote signs (this probably will make it worse?)
where (fieldon = ":fieldone")
and (fieldtwo = ":fieldtwo")
Or, to explore the problem, remove the "and fieldtwo = :fieldtwo" line and see if it runs.
Would it be possible for you to do your own parameter substitution with a StringReplace as in
Query1.SQL.Text := StringReplace(Query1.SQL.Text, ":fieldone", "MyVarName",[rfReplaceAll ]);
If you are creating a ClienDataSet in memory by the Create DataSet method, you should check the TFieldDefs property, which must have a different field name or not created
I was having a weird but small problem, I'll post in case it will help someone in some day.
uRegPeople.pas
with frmEditPerson do
begin
PersonID := qryPerson.FieldByName(ID).AsInteger;
...
end;
I had qryPerson both in frmRegPeople and in frmEditPerson, by using with I was referencing to frmEditPerson.qryPerson, however I wanted to reference to frmRegPeople.qryPerson. Then I need to change to the following code.
with frmEditPerson do
begin
PersonID := Self.qryPerson.FieldByName(ID).AsInteger;
...
end;
// Explanation
// qryPerson --> frmEditPerson.qryPerson;
// Self.qryPerson --> frmRegPeople.qryPerson;

How to "order by" a sfWidgetFormDoctrineChoice in the Admin Generator

I'm using Symfony 1.4 and Doctrine.
Let's say I have 2 classes : a Brand and a Product.
When I create a new product in the Admin Generator based admin, I'd like to choose a brand from a dropdown list.
The Admin Generator is doing that for me, automatically creating a sfWidgetFormDoctrineChoice.
The problem is that the brands are ordered by id. I'd like them to be ordered by their "label" field.
In order to do that I did the following in my ProductForm class:
$this->widgetSchema['brand_id']->addOption('order_by','label');
But I get the following error:
Syntax error or access violation: 1064
You have an error in your SQL syntax;
check the manual that corresponds to
your MySQL server version for the
right syntax to use near 'a' at line
1. Failing Query: "SELECT b.id AS b__id, b.external_id AS
b__external_id, b.label AS b__label,
b.created_at AS b__created_at,
b.updated_at AS b__updated_at FROM
brand b ORDER BY l a"
The order by statement is really weird. I don't understand why it seems to cut the name of the order by statement.
Edit: Apparently the 'order_by' option is expecting an array as a second parameter. What values does it expect?
I didn't try benlumley's solution since he answered right when I found my solution. It seems more tedious than what I ended doing.
I took a look at the source code to figure out how all this was working.
It turns out the "order_by" option needs an array specifying the field on which one wants to order the results and either 'asc' or 'desc':
$this->widgetSchema['product_id']->addOption('order_by',array('label','asc'));
It works like a charm.
You should take a look here:
http://trac.symfony-project.org/wiki/HowtoSortAdminGeneratorListByForeignTableName
Its based off of an old version of symfony, so suspect the plugin it links won't work. But I think the method should still be sound - crux of it is that you have to add method to the action to intercept and amend the default handling of sorting by this specific field:
For doctrine, you need to define/override addSortQuery, for propel, addSortCriteria.
Recommend you take a look in the cache folder to see what the auto-generated classes look like to get the hang of how it works.

Resources