MySQL - surrounding precomputed variable with single-quotes prior to inserting - mysql

The primary key of my table is a char of fixed length 11.
I have precomputed the key in my script, just like this:
SET pes = LPAD(person_number, 11, '0');
Now, my variable meets my critera. It only needs to be added to the database.
INSERT INTO db VALUES(pes, ...);
This is where my problem arises - since the primary key is supposed to be a char, I need to put the value of my variable in single quotes.
However, I don't know how to do that.
I tried to escape them, but
'\''pes'\''
doesn't work.
Is there a simple way to accomplish that?

This should not be a problem !
The mySql varchar data-type should accept numbers!
CREATE TABLE USERS (USER_ID VARCHAR(255) NOT NULL UNIQUE PRIMARY KEY,
USER_NAME VARCHAR(255));
SET #U_ID = LPAD(2018, 11, '0');
INSERT INTO USERS VALUES (#U_ID, 'USER_1'),(2, 'USER_2');
SELECT * FROM USERS;
Will output :
USER_ID | USER_NAME
-------------------------
00000002018 | USER_1
2 | USER_2
This is a working fiddle

You can try to use multi-single-quotes with concat function.
INSERT INTO db VALUES(concat('''', #pes,''''), ...);
Here is a sample
Schema (MySQL v5.7)
CREATE TABLE T(col varchar(50));
SET #pes = '1234';
INSERT INTO T VALUES (concat('''', #pes,''''));
Query #1
select col
FROM T;
| col |
| ------ |
| '1234' |
View on DB Fiddle

Related

MySQL unique index on VARCHAR column (but only if longer than x characters) [duplicate]

I am using mysql db. I know postgresql and SQL server supports partial Indexing. In my case I want to do something like this:
CREATE UNIQUE INDEX myIndex ON myTable (myColumn) where myColumn <> 'myText'
I want to create a unique constraint but it should allow duplicates if it is a particular text.
I couldn't find a direct way to do this in mysql. But, is there a workaround to achieve it?
Filtered indexes could be emulated with function indexes and CASE expression(MySQL 8.0.13 and newer):
CREATE TABLE t(id INT PRIMARY KEY, myColumn VARCHAR(100));
-- NULL are not taken into account with `UNIQUE` indexes
CREATE UNIQUE INDEX myIndex ON t((CASE WHEN myColumn <> 'myText' THEN myColumn END));
-- inserting excluded value twice
INSERT INTO t(id, myColumn) VALUES(1, 'myText'), (2, 'myText');
-- trying to insert different value than excluded twice
INSERT INTO t(id, myColumn) VALUES(3, 'aaaaa');
INSERT INTO t(id, myColumn) VALUES(4, 'aaaaa');
-- Duplicate entry 'aaaaa' for key 'myIndex'
SELECT * FROM t;
db<>fiddle demo
Output:
+-----+----------+
| id | myColumn |
+-----+----------+
| 1 | myText |
| 2 | myText |
| 3 | aaaaa |
+-----+----------+
I suppose there is only one way to achieve it. You can add another column to your table, create index on it and create trigger or do insert/update inside your stored procedures to fill this column using following condition:
if value = 'myText' then put null
otherwise put value
Hope it helps

selecting a column from multiple tables in mysql

TABLE 1
+----+-------+-------+-------+
| uid | color | brand | model |
+----+-------+-------+-------+
| 10 | 1 | 2 | 1 |
+----+-------+-------+-------+
TABLE 2
+----+-------+-------+-------+
| uid | quantity |model |color|
+----+-------+-------+-------+
| 25 | 2 | 2 | 1 |
+----+-------+-------+-------+
I have many tables like this where the uid column is present in every table.I have a value in a variable, say var1=25. I want to check whether var1 value matches with any of the uid value of any table.If it matches I want to print the table name. Can anyone help me with this?
I tried doing this and I found
SELECT `COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`='yourdatabasename'
AND `TABLE_NAME`='yourtablename';
But this is not giving what I want since I want to select all the tables in a database irrespective of the table name.If in future any table is added then it should also get selected.
At first, information_schema table doesn't have specific tuple data.
I suggest you to consider different design.
A. Make a meta table and use triggers(attached to base tables) to maintain meta table.
CREATE TABLE meta_table (
id INT AUTO_INCREMENT,
uid INT,
table_name VARCHAR(50)
);
# When you need to add new table (table 3)
CREATE TABLE table_3 (
uid INT,
field1 INT,
field2 INT,
field3
);
DELIMITER $$
CREATE TRIGGER table_3_insert
AFTER INSERT ON table_3
FOR EACH ROW
BEGIN
INSERT INTO meta_table (uid, table_name)
VALUE (NEW.uid, "table_3");
END$$
DELIMITER ;
# If data in `table_3` might be changed or deleted,
# then create trigger for `delete` and `update`
B. Use only one table with unstructured field and parse data field in your application
CREATE TABLE table (
uid INT,
table_type INT,
data VARCHAR(255)
);
INSERT INTO table (10, 1, '{"color":1,"brand":2,"model":1}');
INSERT INTO table (10, 2, '{"quantity":2,"model":2,"color":1}');
As you mentioned "any table can be added" often, I strongly recommend B solution. It is not good design that changing schema(creating table) often.

Is there a way to use the current row's (that is about to be inserted) id number inside query itself? [duplicate]

This question already has answers here:
(mysql, php) How to get auto_increment field value before inserting data?
(8 answers)
Closed 8 years ago.
I want to use the id for naming the image file inside a row. Is there a way to use the id of the (current) row inside the query itself. (I know about the lastInsertId() but it works generally after the query and not inside it.)
INSERT INTO table (id, intro, detail, image)
VALUES (null, introtext, detailtext, get_the_id_of_this_query_itself.jpg )
I know that i could just save the extension of this image (like .jpg) and then afterwards use it together with the id of the article. But i wondered if this is possible.
added afterwards:
Could we perhaps use a subquery inside the insert query that increments max(id) by one and then add .jpg string for the image name ?
INSERT INTO table (id, intro, detail, image)
SELECT id, 'introtext', 'detailtext', CONCAT('id_', id, '.jpg')
FROM ( SELECT AUTO_INCREMENT AS id
FROM `information_schema`.`TABLES`
WHERE `TABLE_SCHEMA` LIKE 'database_name' AND `TABLE_NAME` LIKE 'table') AS h
INSERT ... SELECT
AUTO_INCREMENT
get privileges for information_schema
from clause subqueries
Replace table and database_name accordingly.
It is not possible to know what the ID will be before insertion. It's also not recommended to use this data as a real value. This column is supposed to be a transparent identifier of the row. This is useful for JOINs. The fact that it can be convenient for lookups is incidental and should not be relied upon.
This ID should be treated as if it could change at any time. If you need another identifier such as an ordinal number, it should be stored in a separate field and handled by the application.
Imagine if this script is being accessed at high speed. Many of these INSERT queries may be running simultaneously (and even on different servers) so the ID cannot be known until the query completes. Even after the query completes, the ID may be changed after replication syncs and the image column's data may be inconsistent.
Even though technically you can achieve this in MySQL with a separate table for sequencing and a BEFORE trigger
Table schemas:
CREATE TABLE articles_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE articles
(
`id` INT NOT NULL PRIMARY KEY DEFAULT 0,
`intro` VARCHAR(128),
`detail` VARCHAR(128),
`image` VARCHAR(128)
);
The trigger:
DELIMITER $$
CREATE TRIGGER tg_bi_articles
BEFORE INSERT ON articles
FOR EACH ROW
BEGIN
INSERT INTO articles_seq () VALUES ();
SET NEW.id = LAST_INSERT_ID(),
NEW.image = CONCAT(NEW.id, '.jpg');
END$$
DELIMITER ;
Now you can insert records like this
INSERT INTO articles (`intro`, `detail`, `image`) VALUES
('Intro text 1', 'Details text 1', '.jpg'),
('Intro text 2', 'Details text 2', '.png');
Outcome:
| ID | INTRO | DETAIL | IMAGE |
|----|--------------|----------------|-------|
| 1 | Intro text 1 | Details text 1 | 1.jpg |
| 2 | Intro text 2 | Details text 2 | 2.jpg |
Here is SQLFiddle demo
you better off without it. You can use a view instead
CREATE TABLE articles
(
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`intro` VARCHAR(128),
`detail` VARCHAR(128),
`ext` VARCHAR(32)
);
CREATE VIEW vw_articles AS
SELECT id, intro, detail, CONCAT(id, '.', ext) image
FROM articles;
Here is SQLFiddle demo

Is there a way to insert an auto-incremental primary id with a prefix in mysql database?

I'm trying to insert a data as a primary ID that has one alphanumerical value and two numerical value in MySQL database. This data will auto incrementally generate number, but the alphanumerical value will be fixed. Like, D1, D2....D54, D55, D56 etc. Here, 'D' is always the same, but the number will be automatically incremented. Is there any way to do this?
First of all it's unadvisable to do so, like others commented, you can have this id value generated on the fly.
But if nonetheless you want it your way there're at least two ways to do so:
More or less reliable way involves using a separate table for sequencing and a trigger
Schema:
CREATE TABLE Table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE Table1
(
`id` VARCHAR(10) NOT NULL PRIMARY KEY DEFAULT '',
...
);
Trigger:
DELIMITER $$
CREATE TRIGGER tg_bi_table1
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq() VALUES();
SET NEW.id = CONCAT('D', LPAD(LAST_INSERT_ID(), 4,'0'));
END$$
DELIMITER ;
Then you just insert your rows to table1
INSERT INTO Table1 () VALUES (),(),();
And you'll get
| ID |
---------
| D0001 |
| D0002 |
| D0003 |
Here is SQLFiddle demo
Unreliable way is to generate your new id on the fly in INSERT statement itself
INSERT INTO Table1 (id, ...)
SELECT CONCAT('D', LPAD(COALESCE(SUBSTR(MAX(id), 2), 0) + 1, 4, '0')),
...
FROM table1
Here is SQLFiddle demo
The problems with this approach:
Under heavy load two concurrent sessions can grab the same MAX(id) value and therefore generate the same new id leading to the failure of insert.
You can't use multi-insert statements
We can't set auto-increment for alphanumeric. In your case if D is always same then no need to add it to your pk field. Keep your constant in a separate field and add it when you select.

Workaround in mysql for partial Index or filtered Index?

I am using mysql db. I know postgresql and SQL server supports partial Indexing. In my case I want to do something like this:
CREATE UNIQUE INDEX myIndex ON myTable (myColumn) where myColumn <> 'myText'
I want to create a unique constraint but it should allow duplicates if it is a particular text.
I couldn't find a direct way to do this in mysql. But, is there a workaround to achieve it?
Filtered indexes could be emulated with function indexes and CASE expression(MySQL 8.0.13 and newer):
CREATE TABLE t(id INT PRIMARY KEY, myColumn VARCHAR(100));
-- NULL are not taken into account with `UNIQUE` indexes
CREATE UNIQUE INDEX myIndex ON t((CASE WHEN myColumn <> 'myText' THEN myColumn END));
-- inserting excluded value twice
INSERT INTO t(id, myColumn) VALUES(1, 'myText'), (2, 'myText');
-- trying to insert different value than excluded twice
INSERT INTO t(id, myColumn) VALUES(3, 'aaaaa');
INSERT INTO t(id, myColumn) VALUES(4, 'aaaaa');
-- Duplicate entry 'aaaaa' for key 'myIndex'
SELECT * FROM t;
db<>fiddle demo
Output:
+-----+----------+
| id | myColumn |
+-----+----------+
| 1 | myText |
| 2 | myText |
| 3 | aaaaa |
+-----+----------+
I suppose there is only one way to achieve it. You can add another column to your table, create index on it and create trigger or do insert/update inside your stored procedures to fill this column using following condition:
if value = 'myText' then put null
otherwise put value
Hope it helps