How to create multiple tables using one sql query - php

I'm going to prepare an installation script for my website which is automatically creates database and it's tables.
How can I send every queries in one?
Here is the PHP code:
$table_query = "CREATE TABLE IF NOT EXISTS ".TP."_usertypes(
utid INT(11) NOT NULL AUTO_INCREMENT,PRIMARY KEY (utid),
utname VARCHAR(255)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;
CREATE TABLE IF NOT EXISTS ".TP."_users(
uid INT(11) NOT NULL AUTO_INCREMENT,PRIMARY KEY (uid),
utid INT(11) NOT NULL,FOREIGN KEY (utid) REFERENCES ".TP."_usertypes(utid) ON DELETE RESTRICT,
username VARCHAR(255),
password VARCHAR(255),
avatar VARCHAR(255)
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci";
mysqli_query($connection,$table_query) or die(mysqli_error($connection));
Thank you.

With mysqli you're able to use multiple statements for real using mysqli_multi_query().
Read more on multiple statements in the PHP Docs.

How can I send every queries in one?
You can't.
You need to send each query in a separate php call.

Related

How to fix SQL error with dropping a table in PHP?

I have created a web you can upload and download files - everything works perfect. But now, I want to create a init file, that delete old records in database and create a new tables in it.
So I write this:
$command = "
IF OBJECT_ID(`".$database.".Users`) IS NOT NULL
DROP TABLE ".$database.".Users;
IF OBJECT_ID(`".$database.".Uploads`) IS NOT NULL
DROP TABLE ".$database.".Uploads;
CREATE TABLE `Users` (
`Id` int(11) NOT NULL,
`User` text NOT NULL,
`Password` text NOT NULL,
`Permission` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
ALTER TABLE `Users` ADD PRIMARY KEY (`Id`);
ALTER TABLE `Users` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=0;
CREATE TABLE `Uploads` (
`Id` int(11) NOT NULL,
`Name` text NOT NULL,
`User` text NOT NULL,
`Comment` text NOT NULL,
`Path` text NOT NULL,
`Permission` int(11) NOT NULL,
`Date` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
ALTER TABLE `Uploads` ADD PRIMARY KEY (`Id`);
ALTER TABLE `Uploads` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=0;
";
$result = mysqli_query($conn, $command) or die(mysqli_error($conn));
I think, that code is right (but obviously not). When I run it, SQL throws an 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 'IF OBJECT_ID(db.Users) IS NOT NULL DROP TABLE db.User' at line 1**.
This means that it don’t have a problem with connection to SQL database.
I tried instead of IF OBJECT_ID use IF NOT EXISTS, but it doesn't works too. Can anybody tell me if multi-line SQL command is this problem or if it is something else?
Note: I use 5.5.37 version of MariaDB (if it helps)
IF is not a valid SQL statement in MySQL / MariaDB.
The IF OBJECT_ID(...) statement in the question appears to be a Transact-SQL (Microsoft SQL Server) construct.
The equivalent functionality in MySQL would be achieved with
DROP TABLE IF EXISTS foo.mytable ;
(I expect this would work in MariaDB 5.5, but I haven't verified.)
Note that if the table doesn't exist, the execution of the statement will raise a warning. (A warning message, not an error message.)
The mysqli_query function runs a single statement. To run multiple statements, we can use mysqli_multi_query function, documented here:
http://php.net/manual/en/mysqli.multi-query.php
As far as concerns, OBJECT_ID does not exist in mysql, only in mssql. Searching for OBJECT_ID mysql 8.0 reference manual does not retun anything meaningful. Even if it existed, your syntax for IF block does not look good : you want IF...THEN...END.
To fix the error, you can replace this :
IF OBJECT_ID(`".$database.".Users`) IS NOT NULL
DROP TABLE ".$database.".Users;
IF OBJECT_ID(`".$database.".Uploads`) IS NOT NULL
DROP TABLE ".$database.".Uploads;
With :
DROP TABLE IF EXISTS ".$database.".Users;
DROP TABLE IF EXISTS ".$database.".Uploads;
never used OBJECT_ID but what you want seem to be easily doable with
"drop table if exists users;"

broken UTF8 characters in MySQL using PHP

I have noticed when dealing with some names that are not of normal spelling ie standard alphabet UK/US are getting lost from my inserting of a record to what actually shows up in the database. I have done quiet a bit of reading regarding the Collation type, which is what I thought was causing the issue, but not sure if this is the case or I'm still doing it wrong as my problem is still persisting.
Below is an example of a record I am creating as well as my database structure, and as you can also see the last_name field has "ö", when I lookup the record I actually see the last_name "Körner"
CREATE TABLE `data` (
`id` bigint(20) NOT NULL,
`profile_id` int(11) NOT NULL,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
ALTER TABLE `data`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `profile_id` (`profile_id`);
ALTER TABLE `data`
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT;
INSERT IGNORE INTO data (profile_id, first_name, last_name) VALUES (1, 'Brent', 'Körner');
The field collation on the last_name is set to 'utf8_general_ci' which that I understand or should I say thought would sort this issue out.
This seems to be something I am doing wrong / missing with PHP, as when I execute the INSERT query within PhpMyAdmin it saves fine.
it seems the issue was down to PHP in the end, and i wasn't setting the charset.
For mysql
mysql_set_charset('utf8');
For mysqli
mysqli_set_charset('utf8');
ref https://akrabat.com/utf8-php-and-mysql/

How to store users action (finished queries) in a table?

So this is my situation:
I have an admin user, that can add,delete and edit other users. I'm looking for an a solution how to record the admins action. Should i compare the table, that is affected before and after the query is done and how can i store the difference in another table?
This is the table that would be afected:
TABLE `t_user` (
`user_id` int(11) NOT NULL,
`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` char(32) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`active` tinyint(1) NOT NULL,
`current_desk_book` int(11) NOT NULL,
`last_login` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Lets say the admin tries to delete a user with id=3, the query would be
"DELETE FROM t_user WHERE user_id= 3"
These are the deleted user data:
(3, 'user3', 'fa6daddc77ac9b5ee42ffd31e7d6e014', 'user3#mail.bg', '2016-09-08 11:29:38', 1, 1, NULL)
Im looking to store "Deleted " + the deleted users data in another table.
Two ways :
Simple solution, better have a flag as "deleted" and mark it to "1" admin deletes it. This is soft delete method.
Hard Delete: Create a log table similar to base users table.
Have a trigger, when delete happens. store it into another table.
CREATE TRIGGER log_user_delete AFTER DELETE on users
FOR EACH ROW
BEGIN
INSERT INTO users_log (user_id, username, etc, deletedby_newfield, deletedtime_newfield) values (old.user_id, old.username, '1', NOW());
END
Why you want to store it in database? any specific requirement. Generally people store these kind of information in logs (file). I will suggest that along with deleted use data you should also store the query he has executed that will help you to track things in a better way.
To store the different you can try something like this - whenever he executes a command with where clause you do a select statement with that clause and store it in logs and repeat again after his command execution finishes except in delete case.

How to compare two SQL file query structure in PHP

I have two sql files(t1.sql and t2.sql). Two sql files are different versions and two files contains create queries. I want to compare two sql files query to check the query structures are changed or not.
For example:-
t1.sql file:
CREATE TABLE `static_ids` (
`access_id` int(11) unsigned NOT NULL DEFAULT '0',
`group_id` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`access_id`,`group_id`)
) ENGINE=MyISAM;
t2.sql file:
CREATE TABLE `static_ids` (
`access_id` int(11) unsigned NOT NULL DEFAULT '0',
`group_id` int(11) unsigned NOT NULL DEFAULT '0',
`group_name` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`access_id`,`group_id`)
) ENGINE=MyISAM;
In this example, create query for the table static_ids structure is different.
Kindly give any idea to compare two sql file queries through PHP. Thanks in advance.
To reliably check if the structure is the same using only PHP, you would basically have to rewrite the MySQL parser. It would have to understand, for instance, that
id int;
is equivalent to
`id` int(11) signed DEFAULT NULL;
The much easier solution is to just run the CREATE TABLE command on a blank MySQL database, then do DESCRIBE table_name to a get a list of all the columns that were created as. You can then run through the list of columns for the two tables in a PHPfor` loop and compare them.

Mysql storing lots of bit sized settings

I have ~38 columns for a table.
ID, name, and the other 36 are bit-sized settings for the user.
The 36 other columns are grouped into 6 "settings", e.g. Setting1_on, Setting1_colored, etc.
Is this the best way to do this?
Thanks.
If it must be in one table and they're all toggle type settings like yes/no, true/false, etc... use TINYINT to save space.
I'd recommend creating a separate table 'settings' with 36 records one for each option. Then create a linking table to the user table with a value column to record the user settings. This creates a many-to-many link for the user settings. It also makes it easy to add a new setting--just add a new row to the 'settings' table. Here is an example schema. I use varchar for the value of the setting to allow for later setting which might not be bits, but feel free to use TINYINT if size is an issue. This solution will not use as much space as the one table with the danger of a large sparsely populated set of columns.
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`address` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `setting` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `setting_user` (
`user_id` int(11) NOT NULL DEFAULT '0',
`setting_id` int(11) unsigned NOT NULL,
`value` varchar(32) DEFAULT NULL,
PRIMARY KEY (`user_id`,`setting_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
All depends on how you want to access them. If you want to (or must) just select one of them, then go with the #Ray solution. If they can be functionally grouped (really, not some pretend grouping for all those that start with F) ie. you'll always need number of them for a function and reading and writing them doesn't make sense as an individual flag, then perhaps storing them as ints and using logic operaoprs on them might be a goer.
Saying that, unless you are doing a lot of read and writes to the db during a session, bundling them up into ints gives you very little performance wise, it would save some space on the DB, if all the options had to exist. If doesn't exist = false, it could be a toss up.
So all things being unequal, I'd go with Mr Ray.
MySQL has a SET type that could be useful here. Everything would fit into a single SET, but six SETs might make more sense.
http://dev.mysql.com/doc/refman/5.5/en/set.html

Categories