I am having problem updating my field data. For example I have field with data "runner" and I want to update field to "runner, swimmer".In other words I want that my field would never delete previuos data. But now after update I am getting from "runner" to "swimmer" only.
My code now:
function updateUserField($username, $field, $value) {
$q = "UPDATE " . TBL_USERS . " SET " . $field . " = '$value' WHERE username = '$username'";
return mysql_query($q, $this->connection);
}
Thanks for help! And sorry for bad english.
You have the wrong idea. The right way to store lists in a relational database is to use a junction table. This would have one row per user and per "field". In your case, the table would have at least three columns UserId, Field, Value.
Then, the "update" would look like:
insert into UserFields (UserId, Field, Value)
values ($UserId, #Field, $Value);
(Of course, you should be using mysqli_ and parameterized queries, but that is another matter.)
Don't get into the habit of storing lists as strings, when SQL offers a very good method for storing lists.
You need to use the CONCAT() function in MySQL for string concatenation:
UPDATE TBL_USERS SET $field = CONCAT($field, '$value') WHERE username = $username;
Related
I am looking for some inspiration from someone wiser than me with PHP/MySQL.
In have a database application, and in this instance there are two primary tables and one child table.
Primary Table 1 - Documents
Primary Table 2 - JobDesriptions
Child Table - LnkDocuments_JobDescriptions, which as the title suggests is a one to many relational table between the Document and Job Description Table. In my Documents Table I have a field which is a lookup of JobDescriptions and presents options as a checkbox, this field is called 'AppliesTo', because of the way the application works, the field stores the results as a string, eg "1,2,3,4,5) I have used the explode function to turn this into an array and then insert each record into the child table, as I prefer 1-2-many relationships. This is the code that I have, and it works.
$jdarray = explode(',',$values['AppliesTo']);
foreach($jdarray as $item)
{
$sql2 = "INSERT INTO LnkDocuments_JobDescriptions (DocumentFk, JobDescriptionFk)
values ('".$keys["DocumentPk"]."', '$item')"; CustomQuery($sql2);
}
The problem I now have is that if that table gets updated, I need to also update the child table, i have tried this code (but quickly realised that it is wrong):
$jdarray = explode(',',$values['AppliesTo']);
foreach($jdarray as $item)
{
$sql = "SELECT * FROM LnkDocuments_JobDescriptions WHERE DocumentFk='".$keys["DocumentPk"]."' AND JobDescriptionFk='$item'"; ;
$num_rows = mysql_num_rows(CustomQuery($sql));
if ($num_rows > 0) //Delete Record
{
$sql2 = "DELETE FROM LnkDocuments_JobDescriptions WHERE DocumentFk='".$keys["DocumentPk"]."' AND JobDescriptionFk='$item'"; CustomQuery($sql2);
echo "JD FK : ".$item." deleted";
}
else //Insert Record
{
$sql3 = "INSERT INTO LnkDocuments_JobDescriptions (DocumentFk, JobDescriptionFk)
values ('".$keys["DocumentPk"]."', '$item')"; CustomQuery($sql3);
echo "JD FK : ".$item." added";
}
}
It occured to me that I need to compare differences in the arrays, but havent got a clue how to do this, but this is what I need:
If I can get $oldarray and $new array to compare, for example
if in old array there were values 1,2,3,4 and in $newarray there were values 1,2,3,5, I want the code to loop through each value to determine if there is a change, e.g. if value exists in old and new array then do nothing, if value exists in old array but not new then delete, if value exists in new array but not old then insert.
I have also thought about just deleting all associated records and adding again, but think this is bad practice and will result in high number primary key, also it is worth noting that in my example there are only 5 options, this is just for testing, in reality there could be dozens.
Thanks in advance
If you are trying to optimize things I'm not sure that reading the values already present in the table and then deleting only those are not in the new version while inserting the missing records is the best way to go. In my opinion it would be much faster to just delete everything in one query, then insert all records in one query. Try something like this:
$item_list = implode( ',' , $jdarray );
$delete_query = "DELETE FROM LnkDocuments_JobDescriptions WHERE DocumentFk='".$keys["DocumentPk"]."' AND JobDescriptionFk IN ( $item_list )";
CustomQuery($delete_query);
$document_key = "'" . $keys["DocumentPk"] . "'";
$item_list_to_insert = "($document_key, " . implode( "), ($document_key, ", $jdarray ) . ")";
$insert_query = "INSERT INTO LnkDocuments_JobDescriptions (DocumentFk, JobDescriptionFk) VALUES " . $item_list_to_insert;
CustomQuery($insert_query);
Note: I didn't test this, there might some debugging needed.
This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 7 years ago.
I am working on a project and I I have a scenario like this:
I have many field in my table :
table_name : transaction_tbl
-id
-name
-description
-ref_number : text(datatype)
In my inserting here is my code:
$sql = "INSERT INTO transaction_tbl (`name`,`description`,`ref_number`) VALUES ('$name','$desccription',$ref_number)";
if ($conn->query($sql) === false){
trigger_error('Wrong SQL: ' . $sql . 'Error: ' . $conn->error , E_USER_ERROR);
}else {
echo "Successful ! Data is inserted in database ^__^" ;
}
As the name itself ref_number or reference number, so there will be a time that I will have a lot of reference number,how can I let it insert if it will have multiple values?
Thanks :)
UPDATE :
I want something like this :
name description ref_number
bag to be use 10359435846
05438547656
035848576
Its not a good practice to have multiple values in one cell (and you should never unless there is a serious reason). It violates basic db rules. Just split this to two tables and assign foreign keys to link them up.
Learn db normalization. There are lot of examples. In here you need to take your un-normalized (0NF) table to at least to 1st normalized level (1NF). But its advised to make it normalized at least up to 3rd level
google for db normalization tutorials. As you request below image will give you an idea(field names are not same as in your question).
First insert the values to table1(Member table) and get the insert id in php use $iid = mysqli_insert_id()
Next add the multiple values as seperate rows into the second table(database table) along with the primary key obtained in first step.
Keep in mind this is not a tutorial site. find more info on net.
for what purpose ? why don't you just insert a new row with the same name and description with different ref_number ?
but if you would like that , you can concatenate your new ref_number with the existing ..
first check if it already exist
get its value then concatenate the new ref number ..
or if it doesn't exist , insert a new row ..
$sql = "SELECT `ref_number` FROM `transaction_tbl`
WHERE `name`='$name' AND `description`='$description'";
$query = mysql_query($sql);
if(mysql_num_rows($query) > 0)
{
$row = mysql_fetch_array($query);
$new_ref = $row['ref_number'] . '|' . $ref_number;
$upd = "UPDATE `transaction_tbl` SET `ref_number`='$new_ref'
WHERE `name`='$name' AND `description`='$description'";
}
else
{
$ins = "INSERT INTO transaction_tbl (`name`,`description`,`ref_number`)
VALUES ('$name','$desccription',$ref_number)";
mysql_query($ins);
}
I am trying to use a database where the email can have multiple entries, but i would like to prevent duplicate entries. Currently i have:
<?php
"SELECT Notes, itemName from UserItems where email = '$email'";
if("itemName" == $name && "Notes" == $desc) {
echo "duplicate";
}
?>
But itemName and Notes need to become strings for my if statement to work
My insert function is lower in my code but ill post it
$insert = ("insert into UserItems (itemName, ItemNumber, email, Price, Notes) Value (\"$name\", \"$ItemNumber\", \"$email\", \"$price\", \"$desc\")");
Am I missing something here? I held off answering cause I thought this would be too obvious and my post would waste time -
<?php
// add actual db connection info here
$email = 'someon#somewhere.com';
$name = 'John';
$desc = 'Some Description';
$row = mysql_fetch_array(mysql_query("SELECT Notes, itemName from UserItems where email = '$email'"));
if($row['itemName'] == $name && $row['Notes'] == $desc) {
echo "duplicate";
}
?>
You never actually run a query or fetch the results. Or define the variables you're comparing against. Are they $_POST, $_GET, results of the last row or something?
What about counting the number of entries where email = '$email'?
Based off the conversation we had in the comments, it sounds like your best bet is to handle this functionality at the database layer, by adding a unique contraint across all three columns (email, itemName, notes). With this solution the database will not allow more than one row with the same value for all three columns.
The mysql command would be:
alter table <your_table> add unique (`email`, `itemName`, `notes`);
// Will be inserted/updated no problem
foo#bar.com, itemName1, notes1
foo#bar.com, itemName1, notes2
foo#bar.com, itemName2, notes1
// An error will be returned because this row already exists
foo#bar.com, itemName1, notes2
The only drawback is that writes to the database will more costly as all three columns (notes especially) will have to be considered for the unique constraint.
Your other option is to load all rows matching the email address, then step through each row searching for matches against itemname and notes, which will be even more painful.
What is the easiest / most efficient way to get the entire row inserted after an INSERT statement?
I am pretty sure I could do this as follows:
$aQuery = "INSERT into myTable (a, b, c) VALUES (1, 'Hello', 'Goodbye')";
//the IDENTITY coloumn in myTable is named id
$result = sqlsrv_query($myConn, $aQuery );
if ($result) {
$res = sqlsrv_query('SELECT LAST_INSERT_ID()');
$row = sqlsrv_fetch_array($res);
$lastInsertId = $row[0];
$subQuery = "SELECT * FROM myTable where id = {$lastInsertId}";
$subResult = sqlsrv_query($myConn, $subQuery);
if ($subResult) {
while($subrow = sqlsrv_fetch_array($subResult)) {
echo($subrow ['id'] . ', '.
$subrow ['a'] . ', '.
$subrow ['b']); //etc...
}
}
}
However, I am concerned about the possibility of another insert occurring just before my SELECT LAST_INSERT_ID() and thus messing up my logic to boot. How can I be certain that the last inserted id is truly the INSERT I called previously, and not something happening somewhere else?
Is there a more appropriate way of doing this, perhaps a complete SQL solution (such that the query returns the row automatically rather than using PHP)?
UPDATE: myTable DOES have an explicitly defined (and auto-incremented) identity column, named id.
This will work:
"INSERT into myTable (a, b, c) OUTPUT Inserted.a, Inserted.b, Inserted.c VALUES (1, 'Hello', 'Goodbye')
In Sql Server, you would use select #lastID=SCOPE_IDENTITY()
And #LastID will have the last id inserted for the current scope; therefore, if there was another insertion in the middle, you would still get the correct record on your select.
Never use ##Identity for this or you may end up in a situation like you described.
If you were to use identity field (which maybe you should) there is a command called SCOPE_IDENTIY() which info you can find here:
http://msdn.microsoft.com/en-us/library/ms190315.aspx
Since you do not use it, you do not have to select latest data since you have it when you insert, so just use same data instead of selecting.
I'm new to php. So, please forgive me if this seems like a dumb question.
Say i have a MySQL insert statement insert into table (a,b) values (1,2),(3,4),(5,6). table 'table' has a auto increment field called 'id'.
how can I retrieve all the ids created by the insert statement above?
It will be great if i get an example that uses mysqli.
You can't. I would suggest that you maintain your own ids (using guid or your own auto-increment table) and use it when you insert into the table.
But it's possible to get the auto-increment value for the last inserted using LAST_INSERT_ID():
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
AngeDeLaMort's answer is almost right. Certainly, the most appropriate way to deal with the problem is to insert one row at a time and poll the insert_id or generate the sequence elsewhere (which has additional benefits in terms of scalability).
I'd advise strongly against trying to determine the last insert_id and comparing this the most recent insert_id after the insert - there's just too may ways this will fail.
But...an alternative approach would be:
....
"INSERT INTO destn (id, data, other, trans_ref)
SELECT id, data, other, connection_id() FROM source";
....
"SELECT id FROM destn WHERE trans_ref=connection_id()";
....
"UPDATE destn SET trans_ref=NULL where trans_ref=connection_id()";
The second query will return the ids generated (note that this assumes that you use the same connection for all 3 queries). The third query is necessary because connection ids to go back into the pool when you disconnect (i.e. are reused).
C.
In some cases, if you have another identifier of sort such as a UserID, you could filter your query by UniqueID's greater than or equal to mysql_insert_id(), limit by the number of affected rows and only display those by the user. This would really only work inside of a transaction.
$SQL = "INSERT INTO Table
(UserID, Data)
VALUES
(1,'Foo'),
(1,'Bar'),
(1,'FooBar')";
$Result = mysql_query($SQL);
$LastID = mysql_insert_id();
$RowsAffected = mysql_affected_rows();
$IDSQL = "SELECT RecordID
FROM Table
WHERE UserID = 1
AND RecordID >= '$LastID'
LIMIT '$RowsAffected'";
$IDResult = mysql_query($IDSQL);
as a follow up to AngeDeLaMort:
You could seperate your inserts and do it something like this:
$data = array (
array(1,2),
array(3,4),
array(5,6)
);
$ids = array();
foreach ($data as $item) {
$sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
mysql_query ($sql);
$id[] = mysql_insert_id();
}
Now all your new id's are in the $id array.
Maybe I can do this
$insert = "insert into table (a,b) values (1,2),(3,4),(5,6)";
$mysqli->query($insert);
$rows_to_be_inserted=3;
$inserted_id = $mysqli->insert_id // gives me the id of the first row in my list
$last_row_id = ($inserted_id+$rows_to_be_inserted)-1;
$mysql->query("select * from table where id between $inserted_id and $last_row_id");
what to you guys say?