I am trying call a database-function from HQL. The HQL statement should just call the function and return its value, like this
select someFunction(:someParameter)
If I try to call select current_timestamp().
It fails with
NHibernate.Hql.Ast.ANTLR.QuerySyntaxException: Exception of type 'Antlr.Runtime.MismatchedTreeNodeException' was thrown. near line 1, column 24 [select current_timestamp()]
I know that there is not much reason for retrieving the current timestamp. But I have created a few user-defined database-functions that I would like to unit-test by calling them from HQL.
It seems to me that it's not possible to write a HQL statement without a FROM and WHERE clause. Can this be true?
IQuery query = unitOfWork.Session.CreateQuery("select current_timestamp()");
var ts = query.UniqueResult();
This could work if you explicitly make it an SQL Query, not an HQL query:
var query = unitOfWork.Session.CreateSQLQuery("select current_timestamp()");
It doesn't make much sense to call a function like that. Either you have a stored procedure which should be called using other methods, or you have a function which is not related to the DB at all, and therefore should not be running via the database to begin with.
In any case, if the function doesn't work on a set of rows, can't you just add some dummy FROM clause, for example on a small static table?
Related
if I make a function :
def test
User.where(name: 'foo')
return 42
end
If I call test method the sql is not done.
So where method just construct the request but not execute it.
It's like that we can add where or others sql method like limit, order...etc
Apparently, each time, this method construct request sql but not execute it.
So where, in source code, SQL are execute? What trigger this?
I don't understand the current mechanism...
Firstly I apologise if this is a duplicate!
Say I have a PL/SQL anonymous block stored in a PHP variable $sql, ready to be executed and is laid out thus:
BEGIN
INSERT INTO TABLE_NAME(PARAM1, PARAM2, PARAM3)
VALUES(?,?,?)
RETURNING TABLE_NAME.PARAM1 INTO ?;
END;
Using the Codeigniter framework, I want to be able to perform this statement:
$query = $this->db->query($sql, array('1', 'Hello', 'World', $id));
...and then be able to access the returned variable of '1', which should be stored in the $id variable.
I know that the syntax I have provided wouldn't necessarily work, I've just used it to demonstrate what I'm trying to achieve.
I don't believe the OCI8 driver is equipped to handle returning variables from a statement in this way. I can't seem to find a way to manually bind a variable (in this case $id) to the RETURN...INTO clause of the PL/SQL statement. Normally I could do:
oci_bind_by_name($stid, ':id', $id) //replace '?' with ':id' on the RETURN...INTO section of the anonymous block
...However, I have tried to implement this using the $this->db->call_function() but that did not work either. I have been digging around the code to try and find a way to extend the driver to do this but I fear I may be complicating things or I am going about it the wrong way.
EDITED QUESTION 8/4/14:
I know how to select a column variable I want to return. What I'm unsure about is how I can bind that returned variable to a PHP variable inside the codeigniter framework.
Super thanks in advance! :)
EDIT 1:
I've edited the question to be clearer (emboldened above.)
I'm using the returned value as a foreign key in subsequent statements.
I'm auto incrementing the 'PARAM1' column using a trigger and a sequence.
Oracle has a unique identifier in all tables called rowid.
pleasce check the following select statement
select rowid, *
from ANYTABLE;
you can get the rowid of the inserted record by
BEGIN
INSERT INTO TABLE_NAME(PARAM1, PARAM2, PARAM3)
VALUES(?,?,?)
RETURNING rowid INTO my_output_variable_;
END;
I issue SP from Jsp, code is here:
sql = "EXEC REP_INVOICES ?,?";
java.sql.PreparedStatement ps = cox.prepareStatement(sql);
ps.setEscapeProcessing(true);
ps.setInt(1, cycle);
ps.setInt(2, zone);
ps.execute();
Procedure runs several seconds and fills a table. I want to know when it is over to make outputs. Is it possible?
I has been ages since I did java.
However, there is JDBC and SQL libraries.
I think you are using the first. Here is a link to execute().
http://docs.oracle.com/javase/6/docs/api/java/sql/PreparedStatement.html
I guess the main question is this statement modal? After the execute() does the java wait until the call is finished? I think so.
Have the stored procedure return a value. Check it. After that, you whole table should be populated.
The only other alternative is to do paging. Load only a few records in the table at a time. Should produce quicker response times.
Here is the definition from the manual on return values and how to get them from a SPROC call.
execute
boolean execute()
Executes the SQL statement in this PreparedStatement object, which may be any kind of SQL
statement. Some prepared statements return multiple results; the execute method handles these
complex statements as well as the simpler form of statements handled by the methods
executeQuery and executeUpdate.
The execute method returns a boolean to indicate the form of the first result. You must call
either the method getResultSet or getUpdateCount to retrieve the result; you must call
getMoreResults to move to any subsequent result(s).
I have a PostgreSQL function that takes one string as parameter/this is dynamic sql query/ and executes that dynamic SQL and I expect the result from the dynamic query.
It seems that in PostgreSQL I should predefine what I will return - but this is impossible since I am executing dynamic statement and sometimes I will return one int column, sometimes I will return 5 varchar columns....
Another thing is that existing jdbc code will call the function-and I cannot change it-I can't define the types dynamically like:
{call execute_dynamic(?) as (a varchar(255),b int)};
The code that will call the procedure is:
{call execute_dynamic(?)}
and cannot be changed....
Is there a way to implement this?
The solution is to use refcursor as return type.
OPEN ref_cursor FOR EXECUTE dynamic_sql;
return ref_cursor;
I execute the following simple query in IBExpert firebird2.5 and it works fine:
SELECT
pd.NOME_PRODUTO,
es.QTDE_MINIMA
FROM
TBL_ESTOQUE es,
TBL_PRODUTO pd
WHERE
es.qtde_estoque = 0
AND es.produto = pd.id
ORDER BY
pd.NOME_PRODUTO
But, if I create a stored procedure with two output parameters (see below)
begin
SELECT
pd.NOME_PRODUTO,
es.QTDE_MINIMA
FROM
TBL_ESTOQUE es,
TBL_PRODUTO pd
WHERE
es.qtde_estoque = 0
AND es.produto = pd.id
ORDER BY
pd.NOME_PRODUTO
into :nome_produto, :qtde_minima;
suspend;
end
I get a message like this:
multiple rows in singleton select. multiple rows in singleton
select. At proceddure 'SPD_SALDO_PROD_ZERADO_ESTOQUE' line: 7, col:3"
What is this? I don't understand what is happening...
FOR SELECT ...
INTO ...
DO SUSPEND;
rstrelba's answer shows how to fix the problem. If you want to understand it, here's what's going on.
suspend inside a Firebird stored procedure returns a row to the caller. It can be used in various different ways, and can be thought of as similar to Python's yield statement: suspend operation and send back a single value (or row, in this case), then continue when the caller asks for more data. (It has to be done this way for technical reasons, because database drivers don't always pull the entire result set all at once.)
You've got a select query that can return an arbitrary number of values, followed by a single suspend. Firebird is erroring out, telling you that this is probably wrong. What you want to do is put the select in a for loop, which will loop over the result set and suspend once for each row, as rstrelba's answer demonstrates. This makes sure that the caller gets all the results back.