I have a procedure that creates a table, is it possible to have a view (or similar) that can call the procedure then select from the table?
I've tried this:
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `new_routine`(p1 INT) RETURNS int(1)
BEGIN
CALL rMergeDateFields();
RETURN 1;
END
CREATE VIEW `db`.`vIntervals` AS
SELECT new_routine(0) AS col1;
SELECT * FROM MergedData;
but I get this error
Error 1422: Explicit or implicit commit is not allowed in stored function or trigger.
Any ideas?
No, you cannot. Views are typically read-only operations; and that behavior cannot be guaranteed if stored-procedures are invoked.
Related question:
How to call Stored Procedure in a View?
Is it possible to call stored procedure in view?
Here is a canonical resource:
http://dev.mysql.com/doc/refman/5.1/en/view-updatability.html
Some views are updatable. That is, you can use them in statements such as UPDATE, DELETE, or INSERT to update the contents of the underlying table. For a view to be updatable, there must be a one-to-one relationship between the rows in the view and the rows in the underlying table. There are also certain other constructs that make a view nonupdatable.
As invoking the stored procedure cannot assure 1:1 relationships with view rows, the update is not permitted.
You can't do this from a view, but a stored procedure itself can return a result set.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `merge_and_select` ()
BEGIN
CALL rMergeDateFields();
SELECT * FROM MergeData;
END $$
If you CALL merge_and_select() the rMergeDateFields procedure will be run and then you will get the contents of the MergeData table returned to you, in one step... which sounds like what you're wanting.
This is, however, a really bad implementation, because there's no control for concurrent calls to merge_and_select(), so all kinds of things could go wrong if it's run more than once at the same time.
However, depending on what you really need rMergeDateFields() to do, it's possible that you could rewrite rMergeDateFields() to actually perform whatever work you need done and return it directly to the client without using the MergeData table using an unbounded SELECT, as shown above.
Anything you SELECT in a stored procedure without using INTO a variable is returned to the client as a response from the CALL.
Related
I have a scenario where there is a View 'MyView', a Stored Procedure 'MyProc' and a Table 'MyTable'.
When MyProc is called, it clears the exisiting data in MyTable and based on certain conditions, fills MyTable with the right data. The job of the MyView is to return back the data contained in MyTable.
Eveytime MyView gets called, MyProc needs to be invoked to fill up MyTable.
The question is, how to link MyProc with MyView. Can a stored procedure be invoked from a view and if not, is there any other work around?
Can a stored procedure be invoked from a view
NO, only a function can be used since views are nothing but stored/saved queries.
is there any other work around?
Yes, you can probably as alternative wrap all this steps inside another stored procedure and call that procedure which will in-turn call your myproc
I need to use user variable in prepare statement of mysql
stored procedure. (The purpose is to substitute the table name in
drop table command, which is unable to be injected via ? and
passed via execute using... statement because it is not a data element).
I suppose the user variables are session-wide global variables.
I suppose the stored procedure accessing the user variable must be
synchronized to protect against unwanted behaviour when it is called
simultaneously more times within single session (which I cannot prevent).
How to perform such synchronization?
Is there any chance it is performed internally by the mysql?
It seems like mysql get_lock() & co. uses logic that does not help much:
get_lock('a') followed by get_lock('b') destroys state of a. Maybe I have terribly missed some point here...
For those who would ask the "what exactly would you like to do" question:
drop procedure if exists drop_t_table; delimiter $$
create procedure drop_t_table(in in_t_table_name varchar(128))
begin
declare sql_drop varchar(256) default 'drop temporary table if exists ';
--
-- I would suspect sql_drop_table user variable guard should be locked here...
--
set #sql_drop_table = concat(sql_drop, in_t_table_name);
--
-- What if the procedure is preempted to another call here
-- and the sql_drop_table gets different table name?
--
prepare exe from #sql_drop_table;
--
-- ...and unlocked here
--
execute exe;
deallocate prepare exe;
end$$ delimiter ;
Variables declared within your stored procedure are local to the procedure. An example is sql_drop in your code.
Each session is, basically, single-threaded. You can't do more than one thing at a time within a session. There's no way to call a stored procedure more than once from within a particular session.
If you have more than one session you can call the same stored procedure from both of them. But, a DROP TABLE operation is basically idempotent: If you call it more than once, it has the same effect as calling it just once. It isn't precisely idempotent: it throws an error if the table doesn't exist. But, still, dropping the same table more than once isn't any more destructive than dropping it once.
Temporary tables (a) are only visible to the session that created them, and (b) vanish when the session ends. So, going to a lot of trouble to drop them explicitly might be overkill.
So, with respect, you might be overthinking this problem.
I have MySQL procedure where I want to get a result of query:
SELECT id FROM mbus_clients WHERE second_name like surnamePart AS
So it should be an array. The decision I've found in the internet is to use temporary table.
But how can I return a table and read with PHP? Is it ok?
Simply call the procedure:
CALL procedurename();
If the procedure performs a SELECT, the result set of the procedure call will be the same as if you'd performed the query itself. You can then fetch the rows using PHP the same way as if you'd performed a SELECT.
I have created a procedure in mysql having multiple select statements in it.
Here is my code :
DELIMITER $$
USE `databasename`$$
DROP PROCEDURE IF EXISTS `wholeProjectDetails`$$
CREATE DEFINER=`databasename`#`localhost` PROCEDURE `wholeProjectDetails`(IN givenpid INT)
BEGIN
select * from projects where projectid=givenpid;
select * from projects where projectid<>givenpid;
END$$
DELIMITER ;
When i called this procedure using statement :
call wholeProjectDetails(2);
it is displaying only first statement's results, i want that it will display both statement's records.
Please let me know what i am doing wrong?
Thanks
When you call this procedure, MySQL creates two result-sets. Now, you need to get these two result-sets using your MySQL client. Read information about client you use, does it support this feature? For example, in .NET you can use IDataReader.NextResult Method, in mysqli - mysqli::next_result function, and so on.
If you want just to view these result-sets, you can install one of MySQL GUI tools, there are free ones.
I have execute only access to a stored procedure.
This SP seems to select some data from multiple tables, and returns one row. I need to store two columns of the output of this SP into a table.
Is there any way to do this within MySQL?
If it returns a row, this is a stored function and not a stored procedure. You can use something like the following to insert into your table:
INSERT INTO tablename SELECT (SELECT col1, col2 FROM (SELECT somefunction()))
Otherwise, it will be a stored procedure and you should do something like this, assuming that #var1 and #var2 are output parameters:
CALL someprocedure(#var1, #var2, #var3)
INSERT INTO tablename SELECT(#var1, #var2)
See the documentation about Create Procedure and Create Function for more information about functions versus procedures.
MySQL has an extension to stored procedures that allows the procedure to return one or more result sets to the client, as if the client had issued a SELECT query... but those results are ephemeral. They don't persist and they can't be stored in variables or otherwise accessed after the procedure finishes -- they can only be "fetched" the one time.
There is a way to make them accessible without breaking the way the procedure already works, as I discussed here, but you can't do it without a change to the procedure:
How to use Table output from stored MYSQL Procedure
The idea is for the procedure to write its output in a temporary table, and then return it to the caller by calling SELECT against the temporary table -- but to leave the temporary table behind so that the caller can access it directly if desired.
That's not exactly the same as what you're asking though, which is why I didn't mark this question as a duplicate, since you, unlike the other poster, do not appear to have administrative control of the procedure... but unless you can make the case for a change like this, there's not another way within MySQL to access those returned values, since they only exist in the result-set that's returned.
Of course, procedures do have optional OUT parameters, where you can hand variables to the procedure as part of arguments you use to call it, and it can set those variables, so that they'll have the values you need when the procedure is done, but that only works when the return values are scalars and would require a change to the procedure's interface, since procs in MySQL do not have "optional" arguments... if the procedure were changed to permit this, it would require an increased number of arguments to be provided every time it was called, and if other components are calling it, that could easily break other things.