how create trigger query and using trigger on php - mysql

i have 2 table, table items and table borrowing.
structure items table :
| id | items_name | stock (amount)|
structure borrowing table :
| id | items_id | date | amount |
when someone want to borrow the items, column stock will decrease (minus) as much as loan amount.
so my code is be like :
$items_id = $_POST['items_id'];
$datenow = date('Y-m-d');
$amount = $_POST['amount'];
$input = mysql_query("INSERT INTO borrowing VALUES('$items_id', '$datenow', '$amount')") or die(mysql_error());
$item = mysql_query("SELECT stock FROM items WHERE id='$items_id'");
$row = mysql_fetch_assoc($item);
$stockleft = $row['stock'] - $amount;
$update = mysql_query("UPDATE items SET siswa_nis='$stockleft'") or die(mysql_error());
i am worried if using that, will error on middle run.
what i want is if last query or second query error, first query will rollback, something like that.
so how the trigger and how i call trigger on php ?
thank you in advance.

Related

Mysql Update user Balance SQL syntax Error

I want update an Users Balance but i dont know how i can do it.
With my code its dont work:
$sql = "UPDATE apiusers SET balance = balance - (product_price) WHERE username = (username);";
if(mysqli_query($link, $sql)){
echo "Records added successfully.";
} else{
echo "ERROR: Could not able to execute $sql. " . mysqli_error($link);
}
Table apiuser:
+-------------+
| Field |
+-------------+
| id |
| user |
| pass |
| balance |
| lastip |
| lastlogind |
| email |
| verification|
+-------------+
I would expect something like this:
update apiusers
set balance = balance - ? -- how much to change the balance
where userid = ?; -- which user to change it for
(Of course, I don't know how the users are identified.)
The ? is for parameters to pass in with. You should be using parameters, rather than stuffing the values into strings.
You forgot your equal
$sql = "UPDATE apiusers
SET balance = (balance - product_price)
WHERE user = \"".$username."\";";
\"username\", because " would close the string for $sql and with \" you prevent that.
You need a "Where", so you can update the column with the ID xy.

Update a field if another field has a certain value

I am trying to update a MySQL database but only if a field has the value Approved.
If status is Approved then Date approved should update with the date.
Below is the code I am currently using but cannot get it to work. How to get it to work?
UPDATE my_table
SET `FieldValue`= IF(FieldName='status' AND FieldValue='Approved','".date('m/d/Y')."','')
WHERE `SubmissionId`=".$SubmissionId."
AND FieldName='Date Approved'
Sample Data
+--------+--------------+---------------+--------------+
| FormId | SubmissionId | FieldName | FieldValue |
+--------+--------------+---------------+--------------+
| 6 | 778 | status | Not Approved |
| 6 | 778 | Date Approved | |
+--------+--------------+---------------+--------------+
Use a CASE statement like below:
UPDATE my_table
SET `FieldValue` = CASE WHEN FieldName = 'status'
AND FieldValue='Approved' THEN date('m/d/Y') ELSE `FieldValue` END
WHERE `SubmissionId` = $SubmissionId;
But your query won't make sense; your FieldValue column looks like a string type column and you are trying store a date type data.
Something like this?
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// Fields to update.
$fields = array(
$db->quoteName('FieldValue') . ' = ' . $date->toSql('m/d/Y'))
);
// Conditions for which records should be updated.
$conditions = array(
$db->quoteName('SubmissionId') . ' = SubmissionId',
$db->quoteName('FieldValue') . ' = ' . $db->quote('Approved')
);
$query->update($db->quoteName('#__my_table'))->set($fields)->where($conditions);
$db->setQuery($query);
$result = $db->execute();
Superficially, you should be using the raw SQL like this:
UPDATE my_table
SET FieldValue = date('m/d/Y')
WHERE SubmissionId = 778
AND FieldName = 'Date Approved'
-- AND FieldValue IS NULL -- Optional
-- AND FormId = 6 -- Optional
AND EXISTS (SELECT * FROM my_table
WHERE FieldName = 'status'
AND FieldValue = 'Approved'
AND SubmissionId = 778
-- AND FormId = 6 -- Optional
)
You might need to tart things up a little to get values embedded into the string that forms the SQL statement.
You don't mention FormID in your query; in case of doubt, you should constrain the UPDATE with the correct FormID value, twice, like you constrain the SubmissionID value twice (as shown in the comments). You might decide you only want to update the 'Date Approved' field name when it is NULL (or perhaps blank).
I note that one of the problem with this EAV design is that you lose the type-checking that a normal design gives you. You could store a date (as intended), or a pure number, or pure text, or anything else in the FieldValue column for the 'Date Approved' FieldName and there's nothing to stop that abuse happening. If you had an orthodox typed column, you could ensure that non-dates were never stored in the 'Date Approved' column.
Your UPDATE is tied to a single submission ID; so is mine. It should be possible to enhance things so that all the uninitialized 'Date Approved' columns that are approved and have not previously had the 'Date Approved' value set do in fact have it set.

mysql update table with values from another table?

I am trying to update my table 'supplier_stats' with the values from my other table 'supplier_change_request'.
My two tables look like the following:
Supplier_change_request
id | user_id | company_name | supplier_number
1 123 hewden V0001
Supplier_stats
Id | user_id | company_name | address | reference | supplier_number
1 123 pie n/a 12345 V0001
2 145 gates n/a 12345 V0002
Here is my MySQL:
$reference = '12345'
$query = "UPDATE supplier_stats
SET supplier_stats.company_name = (
SELECT supplier_change_request.company_name
FROM supplier_change_request
WHERE supplier_change_request.reference = '$reference' AND supplier_change_request.supplier_number = supplier_stats.supplier_number";
mysql_select_db('hewden1');
$retval = mysql_query( $query, $conn )
by my calculation this should be setting the value of company_name where supplier_number is 'V0001' in my table 'supplier_stats' to 'hewden'. However the company_name is not being updated.
Can someone please show me where I am going wrong? Thank you in advance
I think the syntax is a bit off in your query and that it should look like this (just the SQL, adapt to PHP as needed):
UPDATE supplier_stats ss
JOIN supplier_change_request scr ON scr.supplier_number = ss.supplier_number
SET ss.company_name = scr.company_name
WHERE ss.reference = '$reference'
The column reference pointed to the supplier_change_request in your sample query, but to supplier_stats in your sample data - I assumed the sample data was correct; change if not.
This query should change the company_name in supplier_stats from pie to hewden.

Perl query and get column name

I need to make a query where I will be looking for a specific string through several columns and I need to know which column (name) contains the value that I need.
In the example below I need a query where I can ask which column contains the value 1000000000002101214 and that it returns f1. DB is MySQL and I need the programming to be done in Perl.
+---------------------+---------------------+---------------------+
| f1 | f2 | f3 |
+---------------------+---------------------+---------------------+
| 1000000000002101214 | 1000000000001989129 | 1000000000001881637 |
| 1000000000002080453 | 1000000000001968481 | 1000000000001862284 |
| 1000000000002085919 | 1000000000001973677 | 1000000000001866854 |
| 1000000000002075076 | 1000000000001963189 | 1000000000001857288 |
+---------------------+---------------------+---------------------+
I was able to find an almost-answer to my question from another site where I could get the column names of the fields in the table with the following:
my #cols = #{$sth->{NAME}}; # or NAME_lc if needed
while (#row = $sth->fetchrow_array) {
print "#row\n";
}
$sth->finish;
foreach ( #cols ) {
printf( "Note: col : %s\n", $_ );
}
The problem is partially resolved. In the example table I provided in the original question I needed to know on which column my answer resides, the query contains several OR statemens:
SELECT * FROM table WHERE (f1='1000000000002101214' OR f2='1000000000002101214' OR f3='1000000000002101214')
And I need the result to show that the column name where the number is located is f1. So....
Any thoughts?
I don't even know where to start
Check out Perl's DBI module. Read the documentation. You'll have to do something like below:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
#Connect to your database, provide id, password
my $dbh = DBI->connect('dbi:mysql:perltest','root','password') or die "Connection Error: $DBI::errstr\n";
#Write your query
my $sql = "select * from database_schema";
my $sth = $dbh->prepare($sql);
#Execute it
$sth->execute or die "SQL Error: $DBI::errstr\n";
#Fetch the value
while (my #row = $sth->fetchrow_array) {
#Do something with your result
print "#row\n";
}
If you are new to Perl then see: http://learn.perl.org/
Edit: Query to find out column name based on the value found in column.
Select 'f1'
from database_schema
where database_schema.f1 = 1000000000002101214
union
Select 'f2'
from database_schema
where database_schema.f2 = 1000000000002101214
union
Select 'f3'
from database_schema
where database_schema.f3 = 1000000000002101214

How do I select noncontiguous characters from a string of text in MySQL?

I have a table with millions of rows and a single column of text that is exactly 11,159 characters long. It looks like this:
1202012101...(to 11,159 characters)
1202020120...
0121210212...
...
(to millions of rows)
I realize that I can use
SELECT SUBSTR(column,2,4) FROM table;
...if I wanted to pull out characters 2, 3, 4, and 5:
1202012101...
1202020120...
0121210212...
^^^^
But I need to extract noncontiguous characters, e.g. characters 1,5,7:
1202012101...
1202020120...
0121210212...
^ ^ ^
I realize this can be done with a query like:
SELECT CONCAT(SUBSTR(colm,1,1),SUBSTR(colm,5,1),SUBSTR(colm,7,1)) FROM table;
But this query gets very unwieldy to build for thousands of characters that I need to select. So for the first part of the question - how do I build a query that does something like this:
SELECT CHARACTERS(string,1,5,7) FROM table;
Furthermore, the indices of the characters I want to select are from a different table that looks something like this:
char_index keep_or_discard
1 keep
2 discard
3 discard
4 discard
5 keep
7 discard
8 keep
9 discard
10 discard
So for the second part of the question, how could I build a query to select specific characters from the first table based on whether keep_or_discard="keep" for that character's index in the second table?
this function does what you want:
CREATE DEFINER = `root`#`localhost` FUNCTION `test`.`getsubset`(selection mediumtext, longstring mediumtext)
RETURNS varchar(200)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'This function returns a subset of characters.'
BEGIN
SET #res:='';
SET #selection:=selection;
WHILE #selection<>'' DO
set #pos:=CONVERT(#selection, signed);
set #res := concat_ws('',#res,SUBSTRING(longstring,#pos,1));
IF LOCATE(',',#selection)=0 THEN
SET #selection:='';
END IF;
set #selection:=SUBSTRING(#selection,LOCATE(',',#selection)+1);
END WHILE;
RETURN #res;
END
Note: the CONVERT('1,2,3,4',signed) will yield 1, but it will give a warning.
I have it defined to be available in the database test.
The function takes two parameters; a string(!) with a list of positions, and a long string from where you want the characters taken.
An example of using this:
mysql> select * from keepdiscard;
+---------+------------+
| charind | keepordisc |
+---------+------------+
| 1 | keep |
| 2 | discard |
| 3 | keep |
| 4 | discard |
| 5 | keep |
| 6 | keep |
+---------+------------+
6 rows in set (0.00 sec)
mysql> select * from test;
+-------------------+
| longstring |
+-------------------+
| abcdefghijklmnopq |
| 123456789 |
+-------------------+
2 rows in set (0.00 sec)
mysql> select getsubset(group_concat(charind ORDER BY charind),longstring) as result from keepdiscard, test where keepordisc='keep' group by longstring;
+--------+
| result |
+--------+
| 1356 |
| acef |
+--------+
2 rows in set, 6 warnings (0.00 sec)
The warnings stem from the fast conversion to integer that is done in the function. (See comment above)
How about dynamic sql? (You will need to build the select part of the query)
CREATE PROCEDURE example_procedure()
BEGIN
--
--build the concat values here
--
SET #ids := '';
SET #S = 'SELECT #ids := built_concat_of_values FROM table';
PREPARE n_StrSQL FROM #S;
EXECUTE n_StrSQL;
DEALLOCATE PREPARE n_StrSQL;
END
You can write a php script to do this for you:
<?php
//mysql connect
$conn = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$conn) {
echo 'Unable to connect to DB: ' . mysql_error();
exit;
}
//database connect
$db = mysql_select_db('mydb');
if (!$db) {
echo 'Unable to select mydb: ' . mysql_error();
exit;
}
//get the keep numbers you’re going to use.
//and change the number into string so, for example, instead of 5 you get 'SUBSTR(colm,5,1)'
$result = mysql_query("SELECT number FROM number_table WHERE keep_or_discard='keep'");
$numbers = array();
while ($row = mysql_fetch_assoc($result)) {
$row = 'SUBSTR(colm,' . $row . ',1)';
$numbers = $row;
}
//implode the array so you get one long string with all the substrings
//eg. 'SUBSTR(colm,1,1),SUBSTR(colm,5,1),SUBSTR(colm,12,1)'
$numbers = implode(",", $numbers);
//pull the numbers you need and save them to an array.
$result = mysql_query("SELECT " . $numbers . " FROM table");
$concat = array();
while ($row = mysql_fetch_assoc($result)) {
$concat= $row;
}
And there you have an array with the correct numbers.
I'm sorry if you can't/don't want to use PHP for this, I just don't really know how to do this without PHP, Perl, Python or some other similar language. Hopefully this solution will help somehow...
The source of your difficulty is that your schema does not represent the true relationships between the data elements. If you wanted to achieve this with "pure" SQL, you would need a schema more like:
table
ID Index Char
1 0 1
1 1 2
1 2 0
charsToKeep
ID Index Keep
1 0 false
1 1 true
1 2 true
Then, you could perform a query like:
SELECT Char FROM table t JOIN charsToKeep c ON t.ID = c.ID WHERE c.Keep = true
However, you probably have good reasons for structuring your data the way you have (my schema requires much more storage space per character and the processing time is also probably much longer from what I am about to suggest).
Since SQL does not have the tools to understand the schema you have embedded into your table, you will need to add them with a user-defined function. Kevin's example of dynamic SQL may also work, but in my experience this is not as fast as a user-defined function.
I have done this in MS SQL many times, but never in MySql. You basically need a function, written in C or C++, that takes a comma-delimited list of the indexes you want to extract, and the string from which you want to extract them from. Then, the function will return a comma-delimited list of those extracted values. See these links for a good starting point:
http://dev.mysql.com/doc/refman/5.1/en/adding-functions.html
http://dev.mysql.com/doc/refman/5.1/en/adding-udf.html
To build the concatenated list of indexes you want to extract from the char_index table, try the group_concat function:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
Hope this helps!