I have a csv file which I want to directly use without creating a table. Is there a way to read and manipulate it directly?
As long as you can connect to the server, you will be able to create temp table.
For Microsoft SQL;
declare #TempTable csvtable
(
firstCol varchar(50) NOT NULL,
secondCol varchar(50) NOT NULL
)
BULK INSERT #TempTable FROM 'PathToCSVFile' WITH (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n')
GO
For MySQL;
CREATE TEMPORARY TABLE csvtable
LOAD DATA INFILE 'PathToCSVFile'
INTO TABLE csvtable
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
I know this is tagged as MySQL, but I think the question is you just want to run SQL queries on a CSV. If you are open to using Python, you can use FugueSQL to do that.
A sample Python snippet would be:
from fugue_sql import fsql
query = """
df = LOAD "/path/to/myfile.csv"
SELECT *
FROM df
WHERE col > 1
PRINT
"""
fsql(query).run()
and this will use Pandas to run the query by default. There is also a SAVE keyword so you can save the output to another file.
I have a database, let's simply call it 'db', on my computer, with a few tables that have multiple columns and data inside those tables.
I have a software using this database to store configuration elements and some other stuff.
Now, I am releasing a new version of my software, with only slight modifications in the database, i.e. some columns may have been added to tables, or removed (but no column renamed).
I must keep all data, so I would like to transfer it to the new "version" of my database.
What I thought of :
Rename 'db' into 'db_old'.
Install the new database as 'db_new', with the default values in the new columns
For each table, get a list of all the columns from 'db_old' that are present in 'db_new'
Use a INSERT INTO ... SELECT to put that old stuff back into 'db_new'.
drop the old db and use my new db.
Do you think it can work ? Do you have any easy solution ?
Also, I'm absolutely not an SQL expert... And I tried this (without looking if the column has been removed or not yet) :
SELECT
GROUP_CONCAT(COLUMN_NAME
SEPARATOR ',')
INTO #colList FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'db_old'
AND TABLE_NAME = 'configuration';
INSERT
INTO db_new.configuration (SELECT #colList)
SELECT #colList FROM
db_old.configuration;
But it fails on replacing the second #colList by the effective list... Can you also help me on this issue ?
Thank you everyone and have a nice day !
You should first take a dump of your DB Database and create a .sql file. Depending upon on your DB Data, this file can even go in GBs. This SQL File will contain all your tables and all the data inside those tables. I will suggest you open and see the file.
Then you should use this new created file and use it to import all the data into new DB. It will put all those tables, data into this new DB.
Here is how to do that. First create SQL file:
mysqldump -h [SeverIpAddress] -u [UserName] -p[password] YourDbname > db_backup.sql
Use -h [SeverIpAddress] in case of Remote severs. In case, it resdies in your own system, you don't need to use this.
Then You should create your new DB, lets say DB_new. once created, switch to it using use command.
use DB_new
Once done, now import your .SQl file that we have created before using source command.
source YourSQLFilePath
In your case, source db_backup.sql
OK. If anyone ever encounter the same problem, here is the solution.
First, admit you have a database called 'myDatabase', with a table called 'myTable' that you want to "upgrade", i.e. you want to modify the table structure by adding/removing columns but keep the data inside.
First step is to drop foreign keys (if any) and to rename "myTable" :
USE `myDatabase`;
ALTER TABLE `myTable` DROP FOREIGN KEY `my_fk_constraint`;
ALTER TABLE `myTable` RENAME TO `old_myTable`;
Second step is to import the new table structure, by using SOURCE for example.
SOURCE C:/new_table_structure.sql
Third step is optional, but you may need this if your table has a lot of columns :
USE `myDatabase`;
SET GLOBAL group_concat_max_len = 4294967295;
Fourth step is to store the following routine :
delimiter //
DROP PROCEDURE IF EXISTS updateConf//
CREATE PROCEDURE updateConf(IN dbName TEXT, IN old_table TEXT, IN new_table TEXT, IN primary_key_name TEXT)
BEGIN
-- get column count in old table
SELECT count(*)
INTO #colNb
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
-- get string with all column names from old_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO #colNames1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
SET #colNames1 = CONCAT(#colNames1, ',');
-- get string with all column names from new_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO #colNames2
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = new_table;
-- variables initialization
SET #cpt = 1; -- column number counter
SET #pos = 1; -- position of column name first char
SET #vir = 1; -- next comma position
-- start of loop
label: LOOP
IF #cpt <= #colNb THEN
SET #vir = LOCATE(',',#colNames1,#pos); -- localize next comma
SET #colName = SUBSTRING(#colNames1, #pos, #vir - #pos); -- get column name
SET #pos = #vir + 1; -- update next column position
-- if column is in both tables
IF FIND_IN_SET(#colName, #colNames2) AND #colName != primary_key_name THEN
SET #execut = CONCAT("INSERT INTO ", new_table, " (", primary_key_name, ",", #colName, ") SELECT ", primary_key_name, ",", #colName, " FROM ", old_table, " ON DUPLICATE KEY UPDATE ", new_table, ".", #colName, " = ", old_table, ".", #colName);
PREPARE stmt FROM #execut;
EXECUTE stmt;
END IF;
SET #cpt = #cpt + 1; -- counter increment
-- when all columns parsed
ELSE
LEAVE label; -- end of loop
END IF;
END LOOP label;
END //
delimiter ;
Final step is to call the procedure on tables, and to drop the temporary table:
CALL updateConf( 'myDatabase', 'old_myTable', 'myTable', 'primaryKeyName' );
DROP TABLE `old_myTable`;
And voila ! Just don't forget to put back the foreign keys you dropped :)
It surely can be done in better ways, but i got this to work correctly.
Thank you everyone !
this below query is working fine for me to export the data from table to csv file but i want handle like if query returns no record then in 'filename.csv' file should contain 'no data found' message for users
-- file name as timestamp
SET #fileName = DATE_FORMAT(NOW(),'%Y-%m-%d-%H:%i:%s');
SET #FOLDER = '/tmp/';
SET #EXT = '.csv';
SET #CMD = CONCAT("SELECT id,name,salary,salaryDate FROM emp1 where name ='some_name' INTO OUTFILE '"
,#FOLDER,#fileName,#EXT,
"' FIELDS ENCLOSED BY '\"' TERMINATED BY ',' ESCAPED BY '\"'",
" LINES TERMINATED BY '\n';");
PREPARE statement FROM #CMD;
EXECUTE statement;
where do i need to change ? Any one can help me ?
You should create stored procedure. Check row numbers using COUNT function, then output one of results you need, for example -
CREATE PROCEDURE procedure1()
BEGIN
IF (SELECT COUNT(*) FROM emp1 where name ='some_name') = 0 THEN
SELECT 'no data found' INTO OUTFILE 'file_name.csv';
ELSE
your code here - SELECT INTO OUTFILE
END IF;
END
I'm trying to import data into a MySQL table with values not defined in the input file. I have this php string concatenated query:
"LOAD DATA LOCAL INFILE '".#mysql_escape_string($this->file_name).
"' IGNORE INTO TABLE `".$this->table_name.
"` FIELDS TERMINATED BY '".#mysql_escape_string($this->field_separate_char).
"' OPTIONALLY ENCLOSED BY '".#mysql_escape_string($this->field_enclose_char).
"' ESCAPED BY '".#mysql_escape_string($this->field_escape_char).
"' LINES TERMINATED BY '". $this->line_separate_char .
"' ".
($this->use_csv_header ? " IGNORE 1 LINES " : "")
Is there a way I can set the account id in this load statement?
As documented under LOAD DATA INFILE Syntax:
The SET clause can be used to supply values not derived from the input file. The following statement sets column3 to the current date and time:
LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, column2)
SET column3 = CURRENT_TIMESTAMP;
You can call functions and SQL statements within load data like this:
load data local infile '/tmp/foo.txt' into table foo
fields terminated by '\t' lines terminated by '\n'
(#col1, #col2)
set myid=#col1,
username=CONCAT(#col2, 'abc', 'xyz');
I have a php page that uploads a txt file into a table,
$sql = "LOAD DATA LOCAL INFILE 'data.txt'
REPLACE
INTO TABLE tempdirtySI
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
";
I want to run a trigger to run after all the data is imported that consists of this code.
UPDATE tempdirtysi
SET TIMESTAM = DATE_FORMAT(STR_TO_DATE(TIMESTAM, '%m/%d/%Y %H:%i:%s'), '%Y-%m-%d %H:%i:%s');
INSERT INTO temploadsi
SELECT * FROM tempdirtysi;
TRUNCATE tempdirtysi;
How do I go about this? I tried to spit the update and the insert into two trigger and that only allows one row to be imported. I also tried to do the update in a php page and have the insert run after update, but that also only runs 1 row.
Maybe there is another way to automate this process
IMHO you don't need a trigger for this. Just execute your sql commands sequentially from your PHP code.
$db = new mysqli('host', 'username', 'password', 'database');
$sql = 'LOAD DATA LOCAL...';
$db->query($sql);
$sql = 'UPDATE tempdirtysi SET ...';
$db->query($sql);
$sql = 'INSERT INTO temploadsi SELECT * FROM tempdirtysi';
$db->query($sql);
$sql = 'TRUNCATE tempdirtysi';
$db->query($sql);