Related
Background: I am building a Springboot+mySQL app that uses Spring Data JPA native queries (i.e. #Query(value = "...", nativeQuery = true) to retrieve database data.
We have to use the same SQL in every query we write to enable certain functionality (this can be seen in the example below). And wanted a way to remove this duplicate SQL and instead only declare it once. An option presented was to pass a dynamic SQL string into a stored procedure and then build a prepared statement by concatenating this dynamic SQL string with our static shared SQL string (show in example below).
Question:
This doesn't seem like a good idea to me, but I am not knowledgeable enough about databases to given the exact technical reasons. Is the below example safe, reasonable, and best-practice? Are there ways to mitigate issues with this approach, or are there other approaches to use instead?
Basic setup code:
-- create tables
CREATE TABLE docs (
id INTEGER PRIMARY KEY,
rev INTEGER NOT NULL,
content VARCHAR(30) NOT NULL
);
CREATE TABLE more_docs (
id INTEGER PRIMARY KEY,
more_content VARCHAR(30) NOT NULL
);
CREATE TABLE docs_metadata (
id INTEGER PRIMARY KEY,
letter VARCHAR(30) NOT NULL
);
CREATE TABLE metadata_nums (
id INTEGER PRIMARY KEY,
metadata_id INTEGER,
num INTEGER NOT NULL
);
-- insert some values
INSERT INTO docs VALUES (1, 1, 'abc');
INSERT INTO docs VALUES (2, 1, 'def');
INSERT INTO docs VALUES (3, 2, 'ghi');
INSERT INTO docs VALUES (4, 1, 'jkl');
INSERT INTO more_docs VALUES (1, 'aaa');
INSERT INTO more_docs VALUES (2, 'bbb');
INSERT INTO more_docs VALUES (3, 'ccc');
INSERT INTO more_docs VALUES (4, 'ddd');
INSERT INTO docs_metadata VALUES (1, 'a');
INSERT INTO docs_metadata VALUES (2, 'b');
INSERT INTO docs_metadata VALUES (3, 'c');
INSERT INTO docs_metadata VALUES (4, 'd');
INSERT INTO metadata_nums VALUES (1, 1, 5);
INSERT INTO metadata_nums VALUES (2, 1, 6);
INSERT INTO metadata_nums VALUES (3, 2, 5);
INSERT INTO metadata_nums VALUES (4, 2, 6);
INSERT INTO metadata_nums VALUES (5, 3, 5);
INSERT INTO metadata_nums VALUES (6, 3, 6);
INSERT INTO metadata_nums VALUES (7, 4, 5);
INSERT INTO metadata_nums VALUES (8, 4, 6);
Approach in question:
-- create stored procedure
DELIMITER //
CREATE PROCEDURE FILTER_EVAL (IN dynamic_statement TEXT, IN num INT, IN letter VARCHAR(1))
BEGIN
SET #dynamic_statement := CONCAT("SELECT X.* FROM (", dynamic_statement, ") X INNER JOIN (SELECT DM.*, MN.num FROM docs_metadata DM INNER JOIN metadata_nums MN ON DM.id = MN.metadata_id) M ON X.id = M.id WHERE M.num = ", num, " AND M.letter = '", letter, "'");
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END//
DELIMITER ;
-- fetch some values
CALL FILTER_EVAL("SELECT * FROM docs WHERE rev = 1", 5, 'b')
INSERT INTO Employees (empId,name,salary,Email_id,DOB)
VALUES
('1','stephen','30000','stephen#gmail.com','1999-02-16'),
('2','andew','40000','andew#gmail.com','1995-12-09'),
('3','dev','16000','dev#gmail.com','1992-08-16'),
('4','jackson','25000','jack#gmail.com','1992-08-16'),
('5','shayam','33000','shaym#gmail.com','1992-08-16'),
('6','abc','31000','abc#gmail.com','1992-08-16'),
('7','xyz','32500','xyz#gmail.com','1992-08-16'),
('8','San','22000','san123#gmail.com','1992-08-16'),
('9','Sonu','29000','hkyadav#gmail.com','1992-08-16');
NOW i added one more column to this existing table.
ALTER TABLE EMPLOYEES
ADD age varchar(10);
INSERT INTO EMPLOYEES (age)
VALUES
(
('21'),
('22'),
('32'),
('35'),
('45'),
('39'),
('28'),
('26'),
('36')
);
I'm getting Error Code: 1136. Column count doesn't match value count at row 1
The above exception is thrown when the number of columns in the insert statement is lesser than the number of values in the query. Please check the column and try to insert the value manually for the first time then run the insert script.
Correct syntax is
INSERT INTO EMPLOYEES (age)
VALUES
(21),
(22),
(32),
(35),
(45),
(39),
(28),
(26),
(36)
;
This either will add new rows with all but age column NULL or will fail if some column is declared NOT NULL and has no DEFAULT value.
Provided the goal is not to add new rows but to update existing ones you need an UPDATE statement, kind of
update EMPLOYEES e,
(values
row (1, 21),
row (2, 22),
row (3, 32),
row (4, 35),
row (5, 45),
row (6, 39),
row (7, 28),
row (8, 26),
row (9, 36)
) t(empId, age)
set e.age = t.age
where e.empId = t.empId;
update EMPLOYEES e,
(values
row (1, 21),
row (2, 22),
row (3, 32),
row (4, 35),
row (5, 45),
row (6, 39),
row (7, 28),
row (8, 26),
row (9, 36)
) t(empId, age)
set e.age = t.age
where e.empId = t.empId;
I'm having a bit of trouble. I need to award an item to users on our site, but I don't want to manually fill in the numbers one by one. Is there a way to set the SQL query to INSERT INTO from UID 9 to 5430 without having to create multiple lines? Here's my example.
INSERT INTO `item_owned` (`id`, `uid`, `iid`, `kind`, `time_owned`, `notes`) VALUES (NULL, 'x', '3626', '1', '1592596732', 'NotBanned')
I'm trying to have the "x" be a number, but to have MYSQL generate multiple numbers from 9 to 5430 without having to generate multiple numbers/code all at once. So something like:
INSERT INTO `item_owned` (`id`, `uid`, `iid`, `kind`, `time_owned`, `notes`) VALUES (NULL, '9 - 5430', '3626', '1', '1592596732', 'NotBanned')
The 9 - 5430 is where the issue is. I want to award the item to everyone who has their number between the number 9 and 5430.
Help appreciated - thanks.
You can use stored procedure in mysql to do this; inside your stored procedure you can use a loop to insert multiple entries. I've provided an example below.
Procedure can be implemented like the code shown here:
delimiter $$
create procedure fill_rows(in start_index int,in termination_point int)
begin
while start_index <= termination_point do
INSERT INTO `item_owned` (`id`, `uid`, `iid`, `kind`, `time_owned`, `notes`) VALUES (NULL, start_index, '3626', '1', '1592596732', 'NotBanned');
set start_index := start_index + 1;
end while;
end $$
delimiter ;
Now whenever you want to insert uid let's say from range x to y. Assume x = 10 and y = 1000 then you can simply insert this records using this one time procedure call like:
call fill_row(10, 1000);
This call will insert 990 new rows with uid values 10, 11, 12 ...1000.
Hope this may help you!
I am trying to make a stored procedure that takes a name/or number and returns a specific value for that name/number
So in this code, I am trying to write a stored procedure taht takes a company name or the cvr number and return the degree of compliance for that company
DROP DATABASE IF EXISTS DRCS;
CREATE DATABASE DRCS;
USE DRCS;
CREATE TABLE Companies (
ID INT not null,
Name varchar(255),
primary key (ID)
);
CREATE TABLE CVR (
ID INT not null,
CVR_Number INT
);
CREATE TABLE Compliance (
ID INT not null,
Complaince_level varchar(255)
);
CREATE TABLE GDPR (
ID INT not null,
GDPR_steps varchar(255)
);
INSERT INTO Companies VALUES
(1, 'TDC'),
(2, 'MAERSK'),
(3, 'LEGO'),
(4, 'SAS'),
(5, 'Carlsberg');
INSERT INTO CVR VALUES
(11, '14773908'),
(12, '32345794'),
(13, '47458714'),
(14, '56994912'),
(15, '61056416');
INSERT INTO Compliance VALUES
(21, '10%'),
(22, '20%'),
(23, '40%'),
(24, '60%'),
(25, '80%');
INSERT INTO GDPR VALUES
(31, '1. Awareness'),
(32, '2. Information you hold'),
(33, '3. Communication privacy information'),
(34, '4. Individuals rights'),
(35, '5. Subject access requests');
#HERE MY PROBLEM STARTS
DELIMITER $$
CREATE PROCEDURE DoC()
BEGIN
SELECT * FROM Companies , CVR, Compliance, GDPR;
END $$
DELIMITER ;
CALL DoC;
There is no relationship between the four tables!
Create rows with common id like id = 1,2,3,4 for all tables and then do a join and then try to list the fields you want to view.
INSERT INTO Companies VALUES
(1, 'TDC'),
(2, 'MAERSK'),
(3, 'LEGO'),
(4, 'SAS'),
(5, 'Carlsberg');
INSERT INTO CVR VALUES
(1, '14773908'),
(2, '32345794'),
(3, '47458714'),
(4, '56994912'),
(5, '61056416');
INSERT INTO Compliance VALUES
(1, '10%'),
(2, '20%'),
(3, '40%'),
(4, '60%'),
(5, '80%');
INSERT INTO GDPR VALUES
(1, '1. Awareness'),
(2, '2. Information you hold'),
(3, '3. Communication privacy information'),
(4, '4. Individuals rights'),
(5, '5. Subject access requests');
select c.id,v.cvr_Number from Companies c, cvr v where c.id = v.id
Similarly add more tables by joining with id. You don't need a procedure to this and a procedure is not designed for this.
You can make with union query for all table. But all select query of clomum count should be same.
DELIMITER $$
CREATE PROCEDURE DoC()
SELECT A.id,A.name FROM
( SELECT id as id , name as name FROM Companies
UNION ALL
SELECT id as id , name as name FROM CVR
UNION ALL
SELECT id as id , name as name FROM Compliance
UNION ALL
SELECT id as id , name as name FROM GDPR) as A
END $$
DELIMITER ;
How to prepend a certain value in a certain column in sql. I would want say "100_" prefixed and updated on foo.value. How should I go about doing this?
create table foo (id, value, ...)
insert into foo (1, 1);
insert into foo (2, 1);
insert into foo (3, 3);
insert into foo (4, 2);
insert into foo (5, 3);
insert into foo (6, 6);
The value column must be varchar datatype.
UPDATE Foo SET Value = '100_' + Value