Run multiple CREATE TABLe queries with MySQL and PHP - php

I need to create a large number of tables at once and add data to the first one using PHP and MySQL. My code looks like this:
$sql = "CREATE TABLE table1 (
code VARCHAR(5) PRIMARY KEY,
name VARCHAR(50) NOT NULL
);";
//adding businesses to table
$sql .= "INSERT INTO table1 (code, name)
VALUES ('CODE', 'name');";
//^this basic idea is run a few more times
$sql .= "CREATE TABLE table2 (
code VARCHAR(5) PRIMARY KEY,
name VARCHAR(50) NOT NULL
);";
//^same basic thing run a bunch more times w/ variations to columns
if ($conn->multi_query($sql) === TRUE) {
echo "<p>Tables created.</p>
Continue";
} else {
echo "<p>Error creating tables: " . $conn->error . "</p>";
}
This only creates the first table and adds the data to it, it won't create any other tables and I get no error messages (the success message is shown). I've been googling a solution for an hour and I can't come up with anything. I'm thinking I need a way to hold off creating the next table until the previous one has been created?
I'm very new to MySQL so newbie-friendly would be very much appreciated:)

Try using backticks in your SQL statements, such as:
$sql .= "CREATE TABLE `table2` (
`code` VARCHAR(5) PRIMARY KEY,
`name` VARCHAR(50) NOT NULL
);";
You should also use backticks in your INSERT statement (and your first CREATE query).
If I'm not mistaken, name is reserved word.

Related

In a 1-1 relationship, why is my insert inserting two records in two tables?

I'm having trouble, as title says, when I INSERT a record in a table that has got a 1-1 relationship with another.
First things first, the SQL code that generates the tables:
DROP TABLE IF EXISTS Facebook_Info;
DROP TABLE IF EXISTS Conversations;
CREATE TABLE IF NOT EXISTS Conversations(
c_id INT AUTO_INCREMENT NOT NULL,
c_start TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
channel ENUM('desktop', 'facebook'),
u_name VARCHAR(20) DEFAULT NULL,
u_email VARCHAR(50) DEFAULT NULL,
PRIMARY KEY(c_id)
);
CREATE TABLE IF NOT EXISTS Facebook_Info (
c_id INT AUTO_INCREMENT NOT NULL,
f_id INT(12) NOT NULL,
PRIMARY KEY(c_id),
FOREIGN KEY(c_id) REFERENCES Conversations(c_id)
);
I assure you this code works: I tested it. I hope this is the best way to provide a 1-1 relationship between Conversations and Facebook_Info.
In any case, now I can introduce you my nightmare: I'm trying to insert a new record in Conversations via PHP (procedural style).
public function create_new_id_conv($channel = 1) {
$w_ch = '';
if ($channel == 2) {
$w_ch = 'facebook';
} else {
$w_ch = 'desktop';
}
$query = "INSERT INTO Conversations (c_id, c_start, channel) VALUES (NULL, CURRENT_TIMESTAMP,'$w_ch')";
$conn = mysqli_connect("localhost", Wrapper::DB_AGENT, Wrapper::DB_PSW, Wrapper::DB_NAME);
$res = mysqli_query($conn, $query);
$id_conv= mysqli_insert_id($conn);
mysqli_free_result($res);
return $id_conv;
}
The Wrapper:: * variables are all set well, in fact, an INSERT operation is done, but not only one! I'm having this situation after I call this function:
This is the content of Conversations table:
And here's the content of Facebook_Info:
What's happening?
I searched and searched...
Then I started to think about what I'm getting here: 2147483647. What represents this number? What's that? Seems like a big number!
And what if my script and my queries were correct but the mistake is the skeleton of my tables?
I must register a 14 digit integer, that is too large for the INT type.
So using BIGINT to store the f_id field made all correct and working!
Hope my mistake helps someone!

Foreign Key Failure in MySQL

I have created a database composed of three tables. This is my query in creating my tables with Foreign Key.
CREATE TABLE reporter
(
reporterid INT NOT NULL AUTO_INCREMENT,
firstname VARCHAR(1000) NOT NULL,
lastname VARCHAR(100) NOT NULL,
PRIMARY KEY (reporterid)
);
CREATE TABLE flood
(
floodid INT NOT NULL AUTO_INCREMENT,
address VARCHAR(500) NOT NULL,
description VARCHAR(1000) NOT NULL,
dateofflood DATE NOT NULL,
timeofflood INT NOT NULL,
PRIMARY KEY (floodid)
);
CREATE TABLE reports
(
reportid INT NOT NULL AUTO_INCREMENT,
timereport NODATATYPE NOT NULL,
datereport DATE NOT NULL,
rid INT NOT NULL,
fid INT NOT NULL,
PRIMARY KEY (reportid),
FOREIGN KEY (rid) REFERENCES reporter(reporterid),
FOREIGN KEY (fid) REFERENCES flood(floodid)
);
I created a system in order for me to add records/row on my database through PHP. This is my code:
<?php
mysql_connect("localhost", "root", "") or die("Connection Failed");
mysql_select_db("flooddatabase")or die("Connection Failed");
$description = $_POST['description'];
$address = $_POST['address']; // Make sure to clean the
$dateofflood=$_POST['dateofflood'];
$timeofflood=$_POST['timeofflood'];
$firstname=$_POST['firstname'];
$lastname=$_POST['lastname'];
$dateofreport=$_POST['dateofreport'];
$timeofreport=$_POST['timeofreport'];
$query = "INSERT into flood(address,description,dateofflood,timeofflood) values ('$address','$description','$dateofflood','$timeofflood')";
$query2 = "INSERT into reporter(firstname,lastname) values ('$firstname','$lastname')";
$query3 = "INSERT into reports(dateofreport,timeofreport) values ('$dateofreport','$timeofreport')";
if(mysql_query($query))
if(mysql_query($query2))
if(mysql_query($query3))
{
echo "";
} else
{
echo "fail";
}
?>
The result that I am getting is fine. It's just that, in my REPORTS table, there is no foreign key that is being generated. For example I input something on my reporter table and flood table, the foreign key 'rid' and 'fid' has no values that references to both tables. Need help thank you.
Get the just inserted Primary key value from flood table insert
query. And store it to a variable say $f_id;
Get the just inserted primary key value from reporter table insert
query and store it to a variable say $r_id;
Now Make your last insert statement like below:
"INSERT into reports(dateofreport,timeofreport,rid,fid) values ('$dateofreport','$timeofreport',$r_id,$f_id)";
I am not giving you a direct copy paste solution.
If you need to know how to get the last inserted id by executing an insert query then look at this link
there is no foreign key that is being generated
I'm not entirely sure what you even mean by that. Foreign keys aren't "generated". Primary keys can be, which you do:
reporterid INT NOT NULL AUTO_INCREMENT
(as well as for your other two tables)
the foreign key 'rid' and 'fid' has no values
Well, look at your query:
INSERT into reports(dateofreport,timeofreport) values ...
Where do you insert values for rid and fid? I'm actually pretty surprised this query works at all, since those columns don't allow NULL values:
rid INT NOT NULL,
fid INT NOT NULL,
(Though your column names also don't line up, so I find it likely that the code you're showing isn't actually the code you're using...) That point aside however, the fact still remains that if you want a value in those fields then you have to put a value in those fields:
INSERT into reports(dateofreport,timeofreport,rid,fid) values ...
After each query, you can get the last generated identifier from mysql_insert_id():
$last_id = mysql_insert_id();
Use that to then populate the values being inserted as foreign keys in subsequent queries.
Also worth noting, the mysql_* libraries are long since deprecated and have been replaced with mysqli_ and other libraries such as PDO. I highly recommend you upgrade to a current technology, since what you're using isn't supported by any vendor.
Additionally, and this is very important, your code is wide open to SQL injection attacks. This basically means that you execute any code your users send you. You should treat user input as values, not as executable code. This is a good place to start reading on the subject, as is this.

How can I avoid creating duplicate rows?

Everything I have searched for and found has yet to work because I am accessing the Table through a php script and differently than everything I see. Anyways,
I am importing Feeds from a website into a mysql table. My table was created like this...
$query2 = <<<EOQ
CREATE TABLE IF NOT EXISTS `Entries` (
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
EOQ;
$result = $db_obj->query($query2);
I enter the data like so....
foreach($rss->channel->item as $Item){
$query5 = <<<EOQ
INSERT INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
$result = $db_obj->query($query5);
}
Now, every time Import new feeds from the site I want to make sure I delete any duplicates that might already be there. Everything I have tried, especially DISTINCT, has not worked for me. Does anyone know what type of query I could use to create a temp table, copy over any distinct rows (ENTIRE ROWS, if a title is the same but the date is different I want to keep that), drop the old table, then rename the tamp table to what I want.... or something similar?
Avoid using the duplicate rows in the first place. Make any unique values into keys. When adding new values to your database, use
REPLACE INTO Entries (feed_id, item_title, item_link, item_date)
VALUES ('$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
The duplicates will be automatically overwritten. Replace is handy because it works like an insert when there is no conflict in the keys, but when there is then it will update the record and bump up any auto-incrementing keys.
EDIT
I've been drumming over this for a while. Here's what I came up with.
The problem with making a multi-column key on (feed_id, item_title, item_link, item_date) is that it will exceed the 1000 byte limitation in MySQL for key length. So instead alter your schema like so:
CREATE TABLE IF NOT EXISTS `Entries` (
`hash` varchar(32),
`feed_id` int(11) NOT NULL,
`item_title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_link` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`item_date` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (hash)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Now when you store a new value, get a hash of the values together:
$hash = md5($get_id . $Item->title . $Item->link . $Item->pubDate);
And for your insert statements use the following:
REPLACE INTO Entries (hash, feed_id, item_title, item_link, item_date)
VALUES ('$hash', '$get_id','$Item->title','$Item->link','$Item->pubDate')
EOQ;
The hash will be a unique representation of the record in it's entirety, and will be easy to compare in order to avoid duplicates. Now when you attempt to add the same record more than once, it will just replace the existing entry, and your query will not fail. As an alternative, you could continue to use insert, and the query will return an error, which you could handle however you want to.
The fastest and easiest way to delete duplicate records is by issuing a very simple command.
ALTER IGNORE TABLE [TABLENAME] ADD UNIQUE INDEX UNIQUE_INDEX ([FIELDNAME])
What this does is create a unique index on the field that you do not want to have any duplicates. The ignore syntax instructs MySQL to not stop and display an error when it hits a duplicate. This is much easier than dumping and reloading a table. It will also add unique indexes so that no new duplicates will be added. Just change you INSERT to INSERT IGNORE.
This also will work, but is not as elegant:
delete from [tablename] where fieldname in (select a.[fieldname] from
(select [fieldname] from [tablename] group by [fieldname] having count(*) > 1 ) a )
Perhaps do something like this:
$query2 = 'CREATE TABLE entries_new LIKE entries';
$result = $db_obj->query($query2);
$query5 = 'INSERT INTO entries_new (feed_id, item_title, item_link, item_date) VALUES ';
foreach($rss->channel->item as $Item){
$query5 .= '('$get_id','$Item->title','$Item->link','$Item->pubDate'),';
}
$query5 = rtrim($query5, ',');
$result = $db_obj->query($query5);
$query6 = "RENAME TABLE entries TO entries_backup, entries_new TO entries";
$result = $db_object->query($query6);
This will create a table called entries_new like your entries table. Make a single insert of data into entries_new and then rename the old table to entries_backup and the new table to entries.
You might also want to consider wrapping this whole sequence up in a transaction.

update then replace dies

If there is a row for user_id then I want to update, if not insert (but I was told to use replace). In the table there is id (which is primary key, auto inc) and user_id (index, session relates to). I have a form that when the data is changed it should be changed in the database for that particular user in session, otherwise it is just added for that particular user in session
if (empty($err)) {
$thesis_Name = mysql_real_escape_string($_POST['thesis_Name']);
$abstract = mysql_real_escape_string($_POST['abstract']);
$query="UPDATE thesis SET thesis_Name ='$thesis_Name',
abstract='$abstract' WHERE id='$_SESSION[user_id]'
IF ROW_COUNT()=0
REPLACE INTO thesis (thesis_Name,abstract)VALUES ('$thesis_Name', '$abstract')
";
mysql_query($query) or die();
// query is ok?
if (mysql_query($the_query, $link) ){
// redirect to user profile
header('Location: myaccount.php?id=' . $user_id);
}
With this the page just dies.
EDIT:
`thesis` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`thesis_Name` varchar(200) NOT NULL,
`abstract` varchar(200) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
)
Thanks so much
You don't need to do the UPDATE first - REPLACE handles all of this for you. From the MySQL manual:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, “INSERT Syntax”.
Therefore, so long as id is a unique key in your thesis table, the only SQL you need is:
REPLACE INTO thesis (id, thesis_Name, abstract)
VALUES ('$_SESSION[userid]', '$thesis_name', '$abstract');
There are a few things in your code that pose problem. First you don't have to do an insert and a replace in the same query : replace will insert if there is no row to replace (besides, I'm not even sure the sql syntax you're using is correct)...
Then you do a mysql_query($query) or die() which is probably where your code dies (maybe due to the fact that the sql syntax you used could be incorrect).
Right after that, you do a mysql_query again, which would reexecute the query a second time. Anyway, if your query didn't work, your code would have died on the previous line...
What you could do would be
$query = "REPLACE INTO blablabla";
if (!mysql_query($query))
echo "the query failed";
else header ("location:blabla");
but your query should mention for which user_id you want to update like this
REPLACE INTO thesis (id, thesis_Name, abstract)
VALUES ('{$_SESSION[userid]}', '$thesis_name', '$abstract');
INSERT
INTO thesis (id, abstract, thesis)
VALUES ('$_SESSION[user_id]', '$abstract', '$thesis_Name')
ON DUPLICATE KEY
UPDATE
abstract = VALUES(abstract),
thesis_Name = VALUES(thesis_Name)
You can do it with prepared statements.You can see an example sql ;
DROP PROCEDURE IF EXISTS `UPDATETHESIS`
|
CREATE PROCEDURE `UPDATETHESIS` (IN _id VARCHAR(50), IN _thesis_name VARCHAR(50), IN _abstract VARCHAR(50))
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY INVOKER
IF EXISTS (SELECT * FROM thesis WHERE id = _id)
BEGIN
UPDATE thesis SET thesis_Name = _thesis_name,
abstract = _abstract WHERE id = _id
END
ELSE
BEGIN
INSERT INTO thesis (thesis_Name,abstract) VALUES (_thesis_name, _abstract)
END
You can call this like CALL UPDATETHESIS(userid, thesis_name, abstratc);

php can't create new database tables via query

Here is the code that should create 2 new tables in MySQL if they do not exist CMS and PAGES, however what is occurring is that CMS is being created but PAGES is ignored and is not created.
Here is the php function responsible for creating tables
private function buildDB() {
#lets create cms table if one does not exist
$make_cms = <<<MySQL_QUERY
CREATE TABLE IF NOT EXISTS cms (
title VARCHAR(150),
bodytext TEXT,
date VARCHAR(100)
)
MySQL_QUERY;
return mysql_query($make_cms);
#lets create pages table if one does not exist
$make_pages = <<<MySQL_QUERY2
CREATE TABLE IF NOT EXISTS pages (
pid int NOT NULL AUTO_INCREMENT, PRIMARY KEY (pid),
title VARCHAR(150),
text TEXT,
date VARCHAR(100)
)
MySQL_QUERY2;
return mysql_query($make_pages);
}
And there ya go that's the function. I ones again will note part one of it works so there for $make_cms does its job and actually makes a table called CMS while the function $make_pages does nothing and fails to create PAGES table.
You're returning from the function before beginning the second CREATE TABLE statement. You'll therefore never reach the second statement.
// Don't return here!
return mysql_query($make_cms);
Instead assign the value and return only if FALSE:
$success_cms = mysql_query($make_cms);
// Return only on error of first table creation
if (!$success) {
return FALSE;
}
// Then create the second table...
If you use echo mysql_error() to output the error, it will tell you. I would guess it is because you have a field named text, which is a reserved word. Try escaping your field names in tics ( ` ) or avoiding reserved words.
#lets create pages table if one does not exist
$make_pages = <<<MySQL_QUERY2
CREATE TABLE IF NOT EXISTS pages (
`pid` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`pid`),
`title` VARCHAR(150),
`text` TEXT,
`date` VARCHAR(100)
)
MySQL_QUERY2;
The query itself seems OK, so one explanation may be that either pages exists already, or the user somehow has no permission to create that particular table.
You can modify your code so it shows what the MySQL server said when running the query:
result = mysql_query($make_pages);
if (!$result) {
echo('Invalid query: ' . mysql_error());
}
change "text TEXT," to text1 TEXT and it should work! remember sql is not case sensitive.

Categories