Execute multiple queries from file fast [duplicate] - php

This question already has answers here:
Running MySQL *.sql files in PHP
(15 answers)
Closed 7 years ago.
I have a file with queries. Something like that:
DROP TABLE IF EXISTS #__assets;
CREATE TABLE IF NOT EXISTS `#__assets` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary Key', `parent_id` int(11) NOT NULL DEFAULT '0' COMMENT 'Nested set parent.', `lft` int(11) NOT NULL DEFAULT '0' COMMENT 'Nested set lft.', `rgt` int(11) NOT NULL DEFAULT '0' COMMENT 'Nested set rgt.', `level` int(10) unsigned NOT NULL COMMENT 'The cached level in the nested tree.', `name` varchar(50) NOT NULL COMMENT 'The unique name for the asset.\n', `title` varchar(100) NOT NULL COMMENT 'The descriptive title for the asset.', `rules` varchar(5120) NOT NULL COMMENT 'JSON encoded access control.', PRIMARY KEY (`id`), UNIQUE KEY `idx_asset_name` (`name`), KEY `idx_lft_rgt` (`lft`,`rgt`), KEY `idx_parent_id` (`parent_id`) ) ENGINE=InnoDB AUTO_INCREMENT=92 DEFAULT CHARSET=utf8;
INSERT INTO #__assets VALUES("1","0","0","165","0","root.1","Root Asset","{\"core.login.site\":{\"6\":1,\"2\":1},\"core.login.admin\":{\"6\":1},\"core.login.offline\":{\"6\":1},\"core.admin\":{\"8\":1},\"core.manage\":{\"7\":1},\"core.create\":{\"6\":1,\"3\":1},\"core.delete\":{\"6\":1},\"core.edit\":{\"6\":1,\"4\":1},\"core.edit.state\":{\"6\":1,\"5\":1},\"core.edit.own\":{\"6\":1,\"3\":1}}");
...
And so...
I can split this file row by row and execute.
But this is slow as I have big file. Do you know any faster way to solve this problem?
Thanks!

Get file content in a variable as a string
and use mysqli_multi_query()
// condition the queries must be ; seprated
<?php
$queries = get_file_content("filename.sql/or_anyotherfile");
$result = mysqli_multi_query($con,$queries);
?>
something like this always works for me

you can execute them directly on server by below command, which will be fastest way-
mysql -u<user> -p<pass> db_name < file.sql

Related

Incorrect prefix key MySQL [duplicate]

This question already has answers here:
What is wrong with my SQL here? #1089 - Incorrect prefix key
(15 answers)
Closed 7 years ago.
I have a problem creating a table with phpmyadmin, which gives me the following error:
#1089 - Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
This is the query that I do:
CREATE TABLE `b2b`.`users` ( `id` BIGINT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(30) NOT NULL ,
`surnames` VARCHAR(80) NOT NULL ,
`birthdate` DATE NOT NULL ,
`drivingdoc` VARCHAR(20) NOT NULL ,
`acdate` DATE NOT NULL ,
`countrydoc` VARCHAR(20) NOT NULL ,
`province` VARCHAR(20) NOT NULL ,
`locality` VARCHAR(35) NOT NULL ,
`address` VARCHAR(150) NOT NULL ,
`number` VARCHAR(20) NOT NULL ,
`flat` VARCHAR(20) NOT NULL ,
`door` VARCHAR(20) NOT NULL ,
`description` VARCHAR(2000) NOT NULL ,
PRIMARY KEY (`id`(7))) ENGINE = InnoDB;
Using MariaDB in ubuntu minimal.
The problem is:
PRIMARY KEY (`id`(7))
You cannot use part of a number as a key, you have to use the whole thing. Also, specifying lengths for numeric types is useless at best, and damaging at worst.
Change to:
PRIMARY KEY (`id`)
That Primary Key syntax is nothing I've ever seen before. Try this:
CREATE TABLE `b2b`.`users` (
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
....
) ENGINE = InnoDB;
Or if you want
CREATE TABLE `b2b`.`users` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
....
PRIMARY KEY (id)
) ENGINE = InnoDB;
You have several errors in your sql, so try to find the difference with this sql
CREATE TABLE `b2b`.`users` ( `id` INT(7) NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(30) NOT NULL ,
`surnames` VARCHAR(80) NOT NULL ,
`birthdate` DATE NOT NULL ,
`drivingdoc` VARCHAR(20) NOT NULL ,
`acdate` DATE NOT NULL ,
`countrydoc` VARCHAR(20) NOT NULL ,
`province` VARCHAR(20) NOT NULL ,
`locality` VARCHAR(35) NOT NULL ,
`address` VARCHAR(150) NOT NULL ,
`number` VARCHAR(20) NOT NULL ,
`flat` VARCHAR(20) NOT NULL ,
`door` VARCHAR(20) NOT NULL ,
`description` VARCHAR(255) NOT NULL ,
PRIMARY KEY (`id`)) ENGINE = InnoDB;

SQL syntax error in PHP code, even though command runs in command line

I'm trying to make some SQL commands in XAMPP. My query returns following error:
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near 'CREATE TABLE IF NOT EXISTS kayttajat ( id INT(10) NOT NULL
AUTO_INCREMENT, tunn' at line 2
I can't find the syntax error. And when I run the exact same command by copy-paste in command line, it works. So do I need some different syntax in PHP code?
Also if I remove the first command, the error message moves to [...] right syntax to use near 'CREATE TABLE IF NOT EXISTS rivit [...]. If I remove second command the error comes from third command and so on. I really don't understand where the error is.
$query='
CREATE DATABASE IF NOT EXISTS asdgfhj;
CREATE TABLE IF NOT EXISTS kayttajat
(
id INT(10) NOT NULL AUTO_INCREMENT,
tunnus1 varchar(32) NOT NULL,
tunnus2 varchar(32) NOT NULL,
nimi varchar(32),
nimi2 varchar(32),
oikeus INT(10) NOT NULL DEFAULT 1,
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS rivit
(
id INT(10) NOT NULL AUTO_INCREMENT,
sivu INT(10) NOT NULL,
kayttaja INT(10) NOT NULL,
sana varchar(500),
kommentti varchar(1000),
aika TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
muutos TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS sivut
(
id INT(10) NOT NULL AUTO_INCREMENT,
nimi varchar(32) NOT NULL,
ohje varchar(2000) NOT NULL,
salaisuus INT(10) NOT NULL DEFAULT 1,
PRIMARY KEY(id)
);
';
$mysqli->query($query) or die($mysqli->error);
The query() method is designed to execute a single query not multiple ones.
What you are looking for is multi_query() to execute multiple queries separated by a semicolon.
$query = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";
/* execute multi query */
if ($mysqli->multi_query($query)) {
...
}
You should use multi_query if you want execute many queries with one command.
Also you don't select database which will used for insert statements.
You should add asdgfhj prefix for all tables or use USE asdgfhj after create table statement.
example with prefix:
<?php
$query='
CREATE DATABASE IF NOT EXISTS asdgfhj;
CREATE TABLE IF NOT EXISTS asdgfhj.kayttajat
(
id INT(10) NOT NULL AUTO_INCREMENT,
tunnus1 varchar(32) NOT NULL,
tunnus2 varchar(32) NOT NULL,
nimi varchar(32),
nimi2 varchar(32),
oikeus INT(10) NOT NULL DEFAULT 1,
PRIMARY KEY (id)
);
';
$mysqli->multi_query($query) or die($mysqli->error);
example with use statement:
<?php
$query='
CREATE DATABASE IF NOT EXISTS asdgfhj;
USE asdgfhj;
CREATE TABLE IF NOT EXISTS kayttajat
(
id INT(10) NOT NULL AUTO_INCREMENT,
tunnus1 varchar(32) NOT NULL,
tunnus2 varchar(32) NOT NULL,
nimi varchar(32),
nimi2 varchar(32),
oikeus INT(10) NOT NULL DEFAULT 1,
PRIMARY KEY (id)
);
';
$mysqli->multi_query($query) or die($mysqli->error);

Simple PHP/MySQL ACL System

I have a simple ACL system in PHP and MYSQL started. I need help finishing it though...
I have 2 Database tables shown below...
user_link_permissions : Holds a record for every user, on every entity/link that permissions apply to...
--
-- Table structure for table `user_link_permissions`
--
CREATE TABLE IF NOT EXISTS `user_link_permissions` (
`id` int(100) NOT NULL AUTO_INCREMENT,
`user_id` int(30) NOT NULL,
`link_id` int(30) NOT NULL,
`permission` int(2) NOT NULL DEFAULT '0',
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2055 ;
intranet_links : Is basically the entity that the permission gives or revokes user access to
--
-- Table structure for table `intranet_links`
--
CREATE TABLE IF NOT EXISTS `intranet_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`description` text NOT NULL,
`url` varchar(255) DEFAULT NULL,
`notes` text,
`user_login` varchar(255) DEFAULT NULL,
`user_pw` varchar(255) DEFAULT NULL,
`active` int(2) NOT NULL DEFAULT '1',
`sort_order` int(11) DEFAULT NULL,
`parent` int(10) NOT NULL DEFAULT '1',
`local_route` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
UNIQUE KEY `local_route` (`local_route`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ;
To save these permissions settings I have a matrix style grid like this below where each checkbox is a record in the user_link_permissions table...
I need help creating a simple ACL function in PHP which can check if a user has permission or not to view a link/entity based on the database results.
On page load I am thinking I can query the user_link_permissions DB table for all records with a matching user ID of the logged in user and store them to a session array variable.
A function could then use that array to check for a link/entity permission using that array value on the entity key.
I just can't visualize how it might look at the moment in PHP.
Any help please?
function aclCanAccess($user_id, $entity_id){
}
$entity_id = 123;
if(aclCanAccess(1, $entity_id){
// yes user can see this item
}else{
// NO user permission denied
}
I will leave writing the code to you for fun.
Assume you are storing all the previously queried permissions in a variable called $_SESSION['acl']
Your ACL function should:
check the session if you already queried that entity
if it is not set, read it from the db
in short
function..... {
if(!isset($_SESSION['acl'][$entity_id])) {
$_SESSION['acl'][$entity_id] = query here to return to you if he has access or not
}
return $_SESSION['acl'][$entity_id];
}
You can also read the entire array when you log in the user. That might also be appropriate. In that case you should be able to just
return $_SESSION['acl'][$entity_id];
But I would then try and catch an exception in case it is not set.

Why CREATE TABLE IF NOT EXISTS always returns false?

i don't know what i am doing wrong here but i have been trying to get this to work for hours. i just want it to create a table that doesn't exist. i made it as simple as i can make it and still it just returns false and doesn't change anything. please let me what i am doing wrong thank you in advance.
$conn=mysql_connect('localhost:3306', 'root', '');
mysql_select_db("test",$conn);
$sql = "CREATE TABLE IF NOT EXISTS 'works' (
`autoPlace` int(11) unsigned NOT NULL auto_increment,
`element` float(255) NOT NULL,
`month` tinyint(4) NOT NULL ,
`mday` tinyint(4) NOT NULL ,
`wday` char(12) NOT NULL ,
`time` smallint(6) NOT NULL,
PRIMARY KEY (`autoPlace`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8";
$thisKeepsReturningFalse= mysql_query($sql);
var_dump($thisKeepsReturningFalse);
When I tried to execute your query I got this error:
Incorrect column specifier for column 'element'
The problem is float(255) is not a valid declaration
It needs to be float(x) where x<=53, or you can use float(x,y) - see mysql docs here
Also, as pointed out in the comments, you have single quotes around works. Remove them or replace them with backticks.
After fixing these errors, I was able to successfully execute your query.
"CREATE" command in MySQL is not return value command so that it always return false(not like SELECT). To check if the command "CREATE" success or not, you can use "SHOW TABLES" to check after executing the "CREATE" command.
When you create a float element you must specify the decimals with a comma.And also the name of the table can't be with this format '' it must to be inside ``.
So in this example the query should be :
CREATE TABLE IF NOT EXISTS `works`
(
`autoPlace` int(11) unsigned NOT NULL auto_increment,
`element` float(255,0) NOT NULL,
`month` tinyint(4) NOT NULL ,
`mday` tinyint(4) NOT NULL ,
`wday` char(12) NOT NULL ,
`time` smallint(6) NOT NULL,
PRIMARY KEY (`autoPlace`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
Note how the float it's float(255,0) and not just 255. You must set this , 0 is the default

Help with sorting results from database (JOIN?) in php

Im upgrading my forum a bit, and want to change the way the topics is listed.
My topics is stored in this table:
CREATE TABLE `forum_emner` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`type_forum` CHAR(9) NOT NULL,
`gjengid` INT(10) UNSIGNED NULL DEFAULT '0',
`sticky` TINYINT(1) UNSIGNED NULL DEFAULT '0',
`emne` VARCHAR(255) NOT NULL,
`innlegg` TEXT NOT NULL,
`brukerid_starter` MEDIUMINT(8) UNSIGNED NOT NULL,
`startet_dato` INT(10) UNSIGNED NOT NULL,
`antall_lest` INT(10) UNSIGNED NULL DEFAULT '0',
`antall_svar` INT(10) UNSIGNED NULL DEFAULT '0',
PRIMARY KEY (`id`),
INDEX `type_forum` (`type_forum`),
INDEX `gjengid` (`gjengid`),
INDEX `sticky` (`sticky`),
INDEX `brukerid_starter` (`brukerid_starter`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM
ROW_FORMAT=DEFAULT
Answers to topics is stored in this table (emneid equals id in the forum_emner table):
CREATE TABLE `forum_svar` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`emneid` INT(10) UNSIGNED NOT NULL,
`brukerid_av` MEDIUMINT(8) UNSIGNED NOT NULL,
`innlegg` TEXT NOT NULL,
`dato` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `emneid` (`emneid`),
INDEX `brukerid_av` (`brukerid_av`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM
ROW_FORMAT=DEFAULT
dato is when the answer was posted (time() in php).
What i want: I want to sort the topics after the field, dato in forum_svar. The topic with the newest answer is on the top, and so on. But if a topic is created after the top topics last answer this topic should be on the top (how a forum actually works).
I've tried myself, but its not working as it should.
SELECT *, `forum_emner`.id AS UnikTradID FROM `forum_emner`
LEFT JOIN `forum_svar` ON (`forum_emner`.id = `forum_svar`.emneid)
WHERE `forum_emner`.type_forum = :type AND `forum_emner`.sticky = 0
ORDER BY `forum_svar`.dato DESC LIMIT :p1, :p2
Any help? :)
A side note: you should use AS as I do bellow to make the query look more readable.
And you shouldn't keep your MySQL field names in something other than English. What if you hire someone not speaking your language? :)
The first thing to do is to get the newest thread ids.
We can do that with such query:
SELECT MAX(fs.id) AS LastThreadId FROM forum_svar AS fs GROUP BY fs.emneid ORDER BY LastThreadId
Now we need to join this result set with the threads to get full thread information.
So we do it like this by putting the first query as a subquery here:
SELECT fs.* FROM forum_svar AS fs LEFT JOIN (SELECT MAX(fs.id) AS LastThreadId FROM forum_svar AS fs GROUP BY fs.emneid ORDER BY LastThreadId DESC) n ON (n.LastThreadId = fs.id) WHERE n.LastThreadId IS NOT NULL
This will now get you the newest threads. Enjoy! :)
P.S. Don't forget to accept the answer if it worked out!

Categories