I have a text file that looks like this:
WPG GRIFFON, WIREHAIRED
AFG HOUND, AFGHAN
IBI HOUND, IBIZAN
WOF HOUND, IRISH WOLF
OTT HOUND, OTTER
PHA HOUND, PHAROAH
DER HOUND, SCOTTISH DEER
JIN JINDO
...
and I am trying to rewrite this line of code so it says the names of the dogs
$link = mysqli_connect($servername, $username, $password, $db) or die(mysqli_error($link));
mysqli_query($link, "CREATE TABLE IF NOT EXISTS `description` (`descID` int(10) NOT NULL AUTO_INCREMENT, `desc` text NOT NULL, PRIMARY KEY (`descID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
mysqli_query($link, "INSERT INTO description (descID, desc) VALUES(1, 'description 1'),(2, 'description 2'),(3, 'description 3'),(4, 'description 4');");
However, I always get an error and it crashes the webpage, because I can't get the file to be read and saved.
$handle = #fopen("names.txt", "r");
while (!feof($handle)) // Loop til end of file.
{
$buffer = fgets($handle, 4096);
$sql = "INSERT INTO data_table ...."
mysql_query($sql,$conn) or die(mysql_error());
}
Do you need to use INSERT statements? There are two other very viable options (a little out of the box, maybe):
LOAD DATA: SQL that loads pre-built CSV data into a table. See the MySQL manual and this SO thread
Example usage (from the linked SO thread):
LOAD DATA INFILE 'path/file.csv'
INTO TABLE tbl_name
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(column1, column2, column3);
mysqlimport: If you have access to the MySql shell, you can use this to import a physical CSV to the db. See the MySQL manual or this post from a random google click
Related
I want to use one form to insert into two different Microsoft sql tables. I tryed to use 2 inserts, but didnt work.
if (isset($_GET['submit'])) {
$sth = $connection->prepare("INSERT INTO DB.dbo.Fehler (QualiID, TestaufstellungID, ModulinfoID, failAfter, Datum, Verbleib, DUTNr) VALUES ($QualiID, $TestaufstellungID,$ModulinfoID,'$failAfter','$Datum','$Verbleib','$DUTNr')");
echo "INSERT INTO DB.dbo.Fehler (QualiID, TestaufstellungID, ModulinfoID, failAfter, Datum, Verbleib, DUTNr) VALUES ($QualiID, $TestaufstellungID,$ModulinfoID,'$failAfter',$Datum,'$Verbleib','$DUTNr')";
$sth->execute();
if($sth)
{
echo "";
}
else
{
echo sqlsrv_errors();
}
$MID = $connection->prepare("MAX(MID) as MID FROM DB.dbo.Fehler WHERE DB.dbo.Fehler.TestaufstellungID = '". $TestaufstellungID . "'");
$MID->execute();
$sth2 = $connection->prepare("INSERT INTO DB.dbo.Fehlerinfo (MID, Tester, Test, Ausfallbedingungen, Fehlerbeschreibung, Ersteller) VALUES ($MID, '$Tester','$Test','$Ausfallbedingungen','$Fehlerbeschreibung','$Ersteller')");
$sth2->execute();
To understand MID is the Primary key of table Fehler and ist the foreign key in the second table Fehlerinfo
Thats why i have the select work around to get the last MID and want to save it in a variable $MID to insert it into the second table.
Is there a smarter solution possible?
As I mentioned in the comments, generally the better way is to do the insert in one batch. This is very over simplified, however, should put you in the right direction. Normally you would likely be passing the values for the Foreign Table in a Table Value Parameter (due to the Many to One relationship) and would encapsulate the entire thing in a TRY...CATCH and possibly a stored procedure.
I can't write this in PHP, as my knowledge of it is rudimentary, but this should get you on the right path to understanding:
USE Sandbox;
--Couple of sample tables
CREATE TABLE dbo.PrimaryTable (SomeID int IDENTITY(1,1),
SomeString varchar(10),
CONSTRAINT PK_PTID PRIMARY KEY NONCLUSTERED (SomeID));
CREATE TABLE dbo.ForeignTable (AnotherID int IDENTITY(1,1),
ForeignID int,
AnotherString varchar(10),
CONSTRAINT PK_FTID PRIMARY KEY NONCLUSTERED(AnotherID),
CONSTRAINT FK_FTPT FOREIGN KEY (ForeignID)
REFERENCES dbo.PrimaryTable(SomeID));
GO
--single batch example
--Declare input parameters and give some values
--These would be the values coming from your application
DECLARE #SomeString varchar(10) = 'abc',
#AnotherString varchar(10) = 'def';
--Create a temp table or variable for the output of the ID
DECLARE #ID table (ID int);
--Insert the data and get the ID at the same time:
INSERT INTO dbo.PrimaryTable (SomeString)
OUTPUT inserted.SomeID
INTO #ID
SELECT #SomeString;
--#ID now has the inserted ID(s)
--Use it to insert into the other table
INSERT INTO dbo.ForeignTable (ForeignID,AnotherString)
SELECT ID,
#AnotherString
FROM #ID;
GO
--Check the data:
SELECT *
FROM dbo.PrimaryTable PT
JOIN dbo.ForeignTable FT ON PT.SomeID = FT.ForeignID;
GO
--Clean up
DROP TABLE dbo.ForeignTable;
DROP TABLE dbo.PrimaryTable;
As i mentioned the answer how it works for me fine atm.
if (isset($_GET['submit'])) {
$failInsert = ("INSERT INTO DB.dbo.Fehler (QualiID, TestaufstellungID, ModulinfoID, failAfter, Datum, Verbleib, DUTNr) VALUES ($QualiID, $TestaufstellungID,$ModulinfoID,'$failAfter','$Datum','$Verbleib','$DUTNr')");
$failInsert .= ("INSERT INTO DB.dbo.Fehlerinfo (MID, Tester, Test, Ausfallbedingungen, Fehlerbeschreibung, Ersteller) VALUES (NULL, '$Tester','$Test','$Ausfallbedingungen','$Fehlerbeschreibung','$Ersteller')");
$failInsert .= ("UPDATE DB.dbo.Fehlerinfo SET DB.dbo.Fehlerinfo.MID = i.MID FROM (SELECT MAX(MID)as MID FROM DB.dbo.Fehler) i WHERE DB.dbo.Fehlerinfo.TestID = ( SELECT MAX(TestID) as TestID FROM DB.dbo.Fehlerinfo)");
$sth = $connection->prepare($failInsert);
$sth->execute();
}
Sorry if this has been asked before, but I couldnt find anything that would relate to my case here on SE.
I am trying to import a CSV file into my Mysql database table with both the table the CSV having the exact same amount and order of columns, except that the table's column ID is not missing in the CSV file.
What I want to achieve is to import the CSV into the table while generating an ID number that automatically increases with each record. This does not seem possible as the CSV always seem to want to insert its data into the first colum in the table, but in my case I would need it to be the 2nd column.
How do I approach this and is there any reference code I can study? I currently am working off this PDO approach but am having the above mentioned difficulties.
PHP
<?php
$databasehost = "localhost";
$databasename = "test";
$databasetable = "sample";
$databaseusername="test";
$databasepassword = "";
$fieldseparator = ",";
$lineseparator = "\n";
$csvfile = "filename.csv";
if(!file_exists($csvfile)) {
die("File not found. Make sure you specified the correct path.");
}
try {
$pdo = new PDO("mysql:host=$databasehost;dbname=$databasename",
$databaseusername, $databasepassword,
array(
PDO::MYSQL_ATTR_LOCAL_INFILE => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
)
);
} catch (PDOException $e) {
die("database connection failed: ".$e->getMessage());
}
$affectedRows = $pdo->exec("
LOAD DATA LOCAL INFILE ".$pdo->quote($csvfile)." INTO TABLE `$databasetable`
FIELDS TERMINATED BY ".$pdo->quote($fieldseparator)."
LINES TERMINATED BY ".$pdo->quote($lineseparator));
echo "Loaded a total of $affectedRows records from this csv file.\n";
?>
Thank you
You can have MySQL set values for certain columns during import. If your id field is set to auto increment, you can set it to null during import and MySQL will then assign incrementing values to it.
LOAD DATA LOCAL INFILE ".$pdo->quote($csvfile)." INTO TABLE `$databasetable`
FIELDS TERMINATED BY ".$pdo->quote($fieldseparator)."
LINES TERMINATED BY ".$pdo->quote($lineseparator))."
SET id=null;
EDIT - In case the ID column is not present in CSV
The col1, col2, col3,... are names of actual columns in the DB table (without id column)
LOAD DATA LOCAL INFILE ".$pdo->quote($csvfile)." INTO TABLE `$databasetable`
FIELDS TERMINATED BY ".$pdo->quote($fieldseparator)."
LINES TERMINATED BY ".$pdo->quote($lineseparator))."
(col1, col2, col3,...)
SET id=null;
The AUTO_INCREMENT attribute can be used to generate a unique identity for new rows. Most version of mysql and engin support this. You need not worry about the ID and can use cron job to insert the needed field and AUTO_INCREMENT will take care of the id itself.
No value was specified for the AUTO_INCREMENT column, so MySQL assigned sequence numbers automatically. You can also explicitly assign 0 to the column to generate sequence numbers, unless the NO_AUTO_VALUE_ON_ZERO SQL mode is enabled. If the column is declared NOT NULL, it is also possible to assign NULL to the column to generate sequence numbers. When you insert any other value into an AUTO_INCREMENT column, the column is set to that value and the sequence is reset so that the next automatically generated value follows sequentially from the largest column value.
You can retrieve the most recent automatically generated AUTO_INCREMENT value with the LAST_INSERT_ID() SQL function or the mysql_insert_id() C API function. These functions are connection-specific, so their return values are not affected by another connection which is also performing inserts.
See example from official link :
[https://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html]
As you want to recreate the table over and over and want to manipulate the Data from the CSV, try this:
// You have to create the TABLE if not exists
$pdo->exec("TRUNCATE TABLE sample"); // No need to drop the table if columns don't change.
$csvContent = file_get_contents($csvfile); // Raw Data from file
$lines = explode("
", $csvContent); // The standard line separator is an ENTER
// Now you have each line separated
for($i = 0; $i < coount($lines); $i++) {
$col = explode(";", $lines[$i]); // Would be a comma
// Now you have each column separated
$pdo->exec("INSERT INTO sample (id, col1, col2, col3 ... coln) VALUES (NULL, '".$col[0]."', '".$col[1]."', '".$col[2]."' ... '".$col[n]."')");
}
This way you can dig into your Data and, besides setting an AUTO_INCREMENT ID, you can validate what is coming from the CSV and can correct/prevent importation errors.
So I have a CSV file that I'm trying to make into a table.
I gave up on the import GUI after too many errors, and am trying to accomplish the import through a php file.
//create table with KNOWN values
mysql_query("CREATE TABLE uri_faculty
(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
id INT(15),
lname VARCHAR(50),
fname VARCHAR(50),
mi VARCHAR(3),
Spc_Title VARCHAR(50),
title VARCHAR(50),
deptid INT(5),
dept VARCHAR(50),
degree1 VARCHAR(10),
earned1 INT(4),
school1 VARCHAR(75),
degree2 VARCHAR(10),
earned2 INT(4),
school2 VARCHAR(75),
degree3 VARCHAR(10),
earned3 INT(4),
school3 VARCHAR(75),
degree4 VARCHAR(10),
earned4 INT(4),
school4 VARCHAR(75),
degree5 VARCHAR(10),
earned5 INT(4),
school5 VARCHAR(75),
degree6 VARCHAR(10),
earned6 INT(4),
school6 VARCHAR(75)
)");
//Get CSV file
$getfile = 'faculty_delim2.csv';
$csvfopen = fopen($getfile, "r");
//loop to fill csvget with arrays
for($i=0;!feof($csvfopen);$i++){
$array = fgetcsv($csvfopen);
$insert = implode("','", $array);
//to exclude the first 2 lines (titles of document)
if($i>=1){
//values to be inserted into SQL are displayed
//echo var_dump($array[$i])." <br> ";
$sqlval = $insert;
// var_dump($sqlval);
//the while loop will constantly place values into the database until the file is finished
mysql_query("INSERT INTO uri_faculty (id,lname,fname,mi,Spc_Title,title,deptid,dept,
degree1,earned1,school1,
degree2,earned2,school2,
degree3,earned3,school3,
degree4,earned4,school4,
degree5,earned5,school5,
degree6,earned6,school6,) VALUES ('$sqlval')
");
}
}
fclose($csvfopen);
echo "complete";
?>
I keep getting an error saying that implode is receiving incorrect parameters, yet every bit of documentation I've found says that I am correct.
I changed the permissions of the file, and it is in the right place.
Instead of this:
for($i=0;!feof($csvfopen);$i++){
$array = fgetcsv($csvfopen);
I would write this:
while ($array = fgetcsv($csvfopen)) {
The loop will automatically finish when there are no more rows to read. Your error is probably an edge case, where the file still thinks it is not at feof but in spite of that, there are no more rows, and fgetcsv returns false.
By the way, two other issues:
You will run into another error soon:
. . . degree6,earned6,school6,) VALUES . . .
You must not put a comma after the last column. Write this instead:
. . . degree6,earned6,school6) VALUES . .
You are wide open to SQL injection issues. What happens when one of your CSV fields contains an apostrophe? You should learn how to use PDO with query parameters. Or failing that, use escaping:
$insert = implode("','", array_map('mysql_real_escape_string', $array));
Finally, you should consider skipping fgetcsv and use LOAD DATA INFILE. Then all your CSV issues, and escaping issues just go away.
mysql_query("LOAD DATA LOCAL INFILE 'faculty_delim2.csv' INTO TABLE uri_faculty IGNORE 2 LINES");
So, a snippet of my code which is resulting in an error is :
$con = mysqli_connect('localhost', 'root', '', 'notesDB');
if(isset($_POST['tableName'])) {
$tName = htmlentities($_POST['tableName']);
$firstQuery = mysqli_query($con,"INSERT into notes(Title) VALUES( '$tName'); CREATE TABLE $tName(id int NOT NULL AUTO_INCREMENT, Title varchar(20) NOT NULL, Description varchar(100), PRIMARY KEY(id));");
if($firstQuery){
header("Location: create2.php");
}
else
echo mysqli_error($con);
}
The output of this is :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE test1(id int NOT NULL AUTO_INCREMENT, Title varchar(20) NOT NULL, D' at line 1
Well, the funny thing is that the exact code (except the variable - I just removed the $ sign) executed perfectly in phpMyAdmin.
Also, to prove that there is nothing really wrong with the php, the query executed without any error when it was only the INSERT query (and not the CREATE query).
mysqli_query can only perform one query at a time.
Try mysqli_multi_query instead.
As an aside creating tables on the fly is usually a sign of larger design issues. Schema should be relatively static while data should be dynamic.
You are trying to run two separate queries at a time in the code, which you can't run like that. You have to run them separately like below:
$con = mysqli_connect('localhost', 'root', '', 'notesDB');
if(isset($_POST['tableName'])) {
$tName = htmlentities($_POST['tableName']);
$firstQuery = mysqli_query($con,"INSERT into notes(Title) VALUES( '$tName')");
$secondQuery = mysqli_query("CREATE TABLE '$tName' (id int NOT NULL AUTO_INCREMENT, Title varchar(20) NOT NULL, Description varchar(100), PRIMARY KEY(id));");
if($firstQuery || $secondQuery){
header("Location: create2.php");
}
else
echo mysqli_error($con);
}
Your database architecture is wrong.
You shouldn't create tables on the fly. So, you have only register whatever new entity with simple regular INSERT query. And then use this entity's id to link records from another [already existing] table.
if(isset($_POST['tableName'])) {
$stm = mysqli_prepare($con,"INSERT into notes(Title) VALUES(?)");
$stm->bind_param("s",$_POST['tableName']);
$stm->execute();
}
In the code below, I allow users to add tables to a MySQL database. Is there a way to print out the most recent 25 tables added?
Thanks in advance,
John
$table = mysql_real_escape_string($_POST['name']);
$query = "CREATE TABLE `$table` (id INT(11) NOT NULL auto_increment, site VARCHAR(350) NOT NULL, cat1 BIGINT(9) NOT NULL, cat2 BIGINT(9) NOT NULL, PRIMARY KEY(id), UNIQUE (site))";
$result = mysql_query($query) or die(mysql_error());
select TABLE_NAME
from INFORMATION_SCHEMA.TABLES
where TABLE_SCHEMA='your_db_name`
order by CREATE_TIME desc
limit 25
This is for MySQL version 5 and above. It will list tables created by your users and you, though.
You can but I'd advise creating a history or audit table of all the table creations (and other relevant activity). For example:
$now = time();
$user = $_SESSION['user'];
$sql = <<<END
INSERT INTO table_history
(table, user, action, action_time)
VALUES
('$table', '$user', 'CREATE', $now)
END;
mysql_query($sql) or die($sql . ': ' . mysql_error());
Also, I'd probably suggest not creating a separate table for each instance you need to use it unless they're going to be really large. Creating another column to identify the user, organization or whatever is often (but not always) a better approach.