I'm building a Joomla website for a homeowner's association. When a user makes a payment, I want the mySQL jos_Payments table (where the payment gets saved) to automatically grab the ID for the home that user lives in.
I've created a trigger on the jos_Payments table, BEFORE INSERT. I'm trying to set the home_id field of the newly added row to be equal to the cb_home_id value that is looked up in the jos_comprofiler table.
SET NEW.home_id = (SELECT cb_home_id FROM jos_comprofiler WHERE jos_comprofiler.user_id = NEW.user_id);
I've searched for help on this, and have tried defining a variable as an intermediate step, and none of it seems to help. It just keeps telling me I have an error in my SQL syntax. The SELECT statment works outside of the trigger, if I use a valid user_id instead of NEW.user_id.
It seems like this should be so simple. Where am I going wrong?
I presume the code sample is part of that BEFORE INSERT trigger which fails creation.
I had a simular issue with Joomla 2.5, unable to create a trigger during the install or update procedure while the sql statements work fine.
You will not be able to create a trigger, function, procedure or any sql statement containing more than 1 semi-colon (;). That's why all other statements seem to work in your script.
I tried many appoaches which did not work including these:
In the manifest file use sql-file:
<install>
<sql>
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
</sql>
</install>
In the manifest file use install-queries:
<install>
<queries>
<query id="1">
CREATE TRIGGER `...` AFTER UPDATE ON `#__...` FOR EACH ROW
BEGIN
...codeline...;
...codeline...;
END
</query>
<query id="2">
...
</query>
</queries>
</install>
(sorry for using blockquotes in stead of code sample, otherwise post will not be shown correctly)
The only way it did work was via the installscript option available since Joomla 2.5, see https://docs.joomla.org/J2.5:Developing_a_MVC_Component/Adding_an_install-uninstall-update_script_file.
This did not work out-of-the-box. I had to remove the access check (the first line with define) and put the following code in the install($parent) and update($parent) functions to add the trigger:
$db = JFactory::getDbo();
$db->setQuery("DROP TRIGGER IF EXISTS `...`");
$db->query();
$query="CREATE TRIGGER `...` AFTER UPDATE ON `#__...` FOR EACH ROW
BEGIN
...codeline...;
...codeline...;
END";
$db->setQuery($query);
$db->query();
if ($error = $db->getErrorMsg()) {
$this->setError($error);
return false;
}
...next sqlstatement or code...
return true;
Make sure the classname in this installer php file matches your component name including init caps, something like:
class com_YourComponentNameInstallerScript
And also, don't forget to open the file with <?php tag but do not put the ?> end tag at the end.
Save the file as php file in the root of your install package at the same level as the manifest file, and add this filename to the manifest file at somewhere between the component description and administration or site tags:
<scriptfile>yourcomponentname_install.php</scriptfile>
This method will also work with creating Stored Procedures and Functions.
Related
I have the following code attempting to truncate a table. The Joomla documentation makes me believe this will work, but it does not. What am I missing?
$db = JFactory::getDbo();
truncate_query = $db->getQuery(true);
//$truncate_query = 'TRUNCATE ' . $db->quoteName('#__mytable');
$truncate_query->truncateTable($db->quoteName('#__mytable'));
$db->setQuery($truncate_query);
echo $truncate_query;
exit();
If I use the line that is commented out to manually generate the SQL, it does work. The reason I am still looking to use the truncateTable function is that I am trying to include the truncation in a transaction. When I use the manual statement, the table is still truncated even if another part of the transaction fails, which is annoying since the other statements rely on data that is truncated, so if the table is emptied when it shouldn't be there is no data left to run the transaction again. Very annoying!
Here's how you call/execute your truncation query:
JFactory::getDbo()->truncateTable('#__mytable');
And now some more details...
Here is the method's code block in the Joomla source code:
public function truncateTable($table)
{
$this->setQuery('TRUNCATE TABLE ' . $this->quoteName($table));
$this->execute();
}
As you can see the truncateTable() method expects a tablename as a string for its sole parameter; you are offering a backtick-wrapped string -- but the method already offers the backtick-wrapping service. (Even if you strip your backticks off, your approach will not be successful.)
The setQuery() and execute() calls are already inside the method, so you don't need to create a new query object nor execute anything manually.
There is no return in the method, so the default null is returned -- ergo, your $truncate_query becomes null. When you try to execute(null), you get nothing -- not even an error message.
If you want to know how many rows were removed, you will need to run a SELECT query before hand to count the rows.
If you want to be sure that there are no remaining rows of data, you'll need to call a SELECT and check for zero rows of data.
Here is my answer (with different wording) on your JSX question.
I'm having a really hard time believing this question has never been asked before, it MUST be! I'm working on a batch file that needs to run some sql commands. All tutorials explaining this DO NOT WORK (referring to this link:Pass parameters to sql script that someone will undoubtedly mention)! I've tried other posts on this site verbatim and still nothing is working.
The way I see it, there are two ways I can approach this:
1. Either figure out how to call my basic MYSQL script and specify a parameter or..
2. Find an equivalent "USE ;" command that works in batch
My Batch file so far:
:START
#ECHO off
:Set_User
set usrCode = 0
mysql -u root SET #usrCode = '0'; \. caller.sql
Simply put, I want to pass 'usrCode' to my MYSQL script 'caller.sql' which looks like this:
USE `my_db`;
CALL collect_mismatch(#usrCode);
I know that procedures are a whole other topic to get into, but assume that the procedure is working just fine. I just can't get my parameter from Batch to MYSQL.
Ideally I would like to have the 'USE' & 'CALL' commands in my Batch file, but I can't find anything that let's me select a database in Batch before CALLing my procedure. That's when I tried the above link which boasts a simple command line entry and you're off to the races, but it isn't the case.
Any help would be greatly appreciated.
This will work;
echo SET #usrCode = '0'; > params.sql
type params.sql caller.sql | mysql -u root dbname
I want to create a deployment script, somehow emulate Oracle deployment scripts, where with ¶m you can use previously declared parameters.
I need to call this script for different users on different databases automatically.
For example my script should be:
USE ¶m;
DROP TABLE IF EXISTS `TEST` ;
CREATE TABLE IF NOT EXISTS `TEST` (X INT(16))
etc....
Of course ¶m is what I would have used in Oracle environment.
Thanks
Updates:
Forgot to mention that I am using a windows environment for now. I have created a batch script to call the mysql script. The easiest way I thought would be to pass to mysql 2 command: 1) use the schema I have as parameter and then call the script which will create the table regardless of the schema. Unfortunately mysql seems to understand that I want to connect to the schema X, but doesn't want to call the script.
REM param is the schema and mainsql is the script
SET param="%1"
SET mainsql="script.sql"
echo %param%
echo %mainsql%
mysql -u <user> --password=<psw> %param% "source %mainsql%;"
As far as I know you can't directly pass variables in to a MySQL script. The best you can do is set user variables in a wrapper shell script. Something like:
passed_var1=$1
passed_var2=$2
mainsql=script.sql
mysql $(usual_parameters) -e "set #user_var1=$passed_var1; set #user_var2=$passed_var2; source $mainsql"
Adjust for actual use, of course.
Im using birt reporting tool since from year. its cool product very good.
Today i got a problem. that i want to set mysql user varible when report loading as a example SET #user="USR009";
I tried several ways to do this i couldnot get the answer could some one help me on this issue very thank full
im stuck on this problem
regards
roshan
You can set the value in the query using a report parameter, and initialize it in the script.
Add a report parameter (PARAMETER_1)
Add "SET #user = QUERY_PARAMETER;" before your select statement in your data set.
While the data set is selected, select the script tab and find the "beforeOpen" drop-down. In here, add a line: this.queryText = this.queryText.replace("QUERY_PARAMETER", params["PARAMETER_1"].value);
The script will replace all instances of QUERY_PARAMETER with the text. You might still need quotes around it in the set statement (i.e SET #user = "QUERY_PARAMETER";).
Problem Was resolved create a SP
delimiter //
Create PROCEDURE abcd(param INT)
BEGIN
SET #USER=param;
SELECT #USER;
END//
And in your query call the SP with varible;
works like charm
Is it possible to create an SQL view in MySQL that takes an input variable say as a function argument? I have found this caption from the MySQL web site but am not sure how to use it as I am quite new to SQL functions. When I run this in the MySQL command prompt ,it gives me errors. Also I am not sure if this is even what I am looking for?
create function book_subject
returns varchar(64) as
return #book_subject;
create view thematical_books as
select title, author
from books
where subject = book_subject();
You are getting errors because the CREATE FUNCTION syntax is incorrect (gotta love those MySQL manual user comments!). The correct syntax for creating this function is as follows:
CREATE FUNCTION book_subject()
RETURNS VARCHAR(64)
RETURN #subject;
The CREATE VIEW syntax is correct.
In order to use the view, you'll need to set the variable #book_subject before you select from the view:
SET #book_subject = 'Epic Poems';
Then when you do a:
SELECT *
FROM thematical_books;
It will return the title and author of all of the books that have a subject of 'Epic Poems'
This is a trick to get around the restriction of MySQL views that "The SELECT statement [of the view] cannot refer to system or user variables." You use a function that just returns the variable, and that function gets called each time the view is used.
This is about as close as you are likely to get. There isn't an official way to get any arguments passed into a view (because how do you supply the argument when the view is referenced in the FROM clause). Using a session global variable and a function as shown is about the only way to achieve the effect. It is sneaky and bug-prone - not good attributes for clean maintainable code.