I have a weather database in MySQL. My database get data from arduino, but sometimes the arduino have some error and send error value in my database. I want to make a stored procedure to reject this error. I want using if then in stored procedure. Example if temperature < 20 then MySQL reject this data. Is it possible? Help me please with the coding
this is my table
CREATE TABLE `cuaca_maritim`.`weather_data` (
`idweather` INT(10) NOT NULL,
`temperature` DECIMAL(4,2) NOT NULL,
`HUMID` DECIMAL(4,2) NOT NULL,
`AIRPRESSURE` DECIMAL(6,2) NOT NULL,
`WIND` DECIMAL(4,2) NOT NULL,
PRIMARY KEY (`idweather`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
Perhaps you just want a view:
create view good_weather_data as
select wd.*
from weather_data
where temperature >= 20;
I don't really see why a stored procedure would be necessary. You might want a trigger that rejects invalid data values when they are loaded.
I think you can use the following stored procedure to do your work.
DELIMITER #
CREATE OR REPLACE PROCEDURE add_weather_data (IN temp INT)
proc_main: BEGIN
IF (temp > 20) THEN
INSERT INTO weather_data(temperature) VALUES (temp);
END IF;
END proc_main #
DELIMITER;
Here I have only consider the temp you can do the same for other parameters also
Related
I use MySQL to manage a database.
I have 2 tables named IDENTITY and OPTIONS in a database named WIFI.
IDENTITY contains 2 fields: USERNAME and PASSWORD.
OPTIONS contains 3 fields: USERNAME, WIFI_SSID and WIFI_PASSWORD.
And there is a procedure accepting these variables as argument:
arg01_USERNAME
arg02_PASSWORD
arg03_WIFI_SSID
arg04_WIFI_PASSWORD
I want to build a procedure in phpMyAdmin to do this operation:
This procedure should check if the arg01_USERNAME and arg02_PASSWORD match the data in IDENTITY. If data not found, then do nothing. Else search for arg01_USERNAME in table OPTIONS and update WIFI_SSID and WIFI_PASSWORD with arg03_WIFI_SSID and arg04_WIFI_PASSWORD. If arg01_USERNAME not found in OPTIONS, then insert a new record into OPTIONS.
Here is the SQL query to define procedure:
CREATE DEFINER=`WIFI`#`localhost` PROCEDURE `INSERT`(IN `arg01_USERNAME` INT(20) UNSIGNED, IN `arg02_PASSWORD` VARCHAR(32), IN `arg03_WIFI_SSID` VARCHAR(32) CHARSET utf8, IN `arg04_WIFI_PASSWORD` VARCHAR(32) CHARSET utf8)
NO SQL
IF EXISTS (
SELECT COUNT(*)
FROM `WIFI`.`IDENTITY`
WHERE `USERNAME` = arg01_USERNAME AND `PASSWORD` = arg02_PASSWORD)
THEN
INSERT INTO `WIFI`.`OPTIONS` (
`USERNAME`,
`WIFI_SSID`,
`WIFI_PASSWORD`
) VALUES (
arg01_USERNAME,
arg03_WIFI_SSID,
arg04_WIFI_PASSWORD
)
ON DUPLICATE KEY UPDATE
`WIFI_SSID` = arg03_WIFI_SSID,
`WIFI_PASSWORD` = arg04_WIFI_PASSWORD
END IF;
ENGINE=InnoDB DEFAULT CHARSET=utf8
Could you please point me out what is wrong with this code?
When I try to define the procedure using this code, phpMyAdmin tells me there is a syntax error near "END IF" part of the code(error 1064).
Sorry for my poor English.
You need to redefined Delimiter to something else, for eg: $$, so that parser does not trigger query execution when it sees ;
At the end, redefine the Delimiter back to ;.
Try:
DELIMITER $$
CREATE DEFINER=`WIFI`#`localhost` PROCEDURE `INSERT`(IN `arg01_USERNAME` INT(20) UNSIGNED, IN `arg02_PASSWORD` VARCHAR(32), IN `arg03_WIFI_SSID` VARCHAR(32) CHARSET utf8, IN `arg04_WIFI_PASSWORD` VARCHAR(32) CHARSET utf8)
NO SQL
IF EXISTS (
SELECT COUNT(*)
FROM `WIFI`.`IDENTITY`
WHERE `USERNAME` = arg01_USERNAME AND `PASSWORD` = arg02_PASSWORD)
THEN
INSERT INTO `WIFI`.`OPTIONS` (
`USERNAME`,
`WIFI_SSID`,
`WIFI_PASSWORD`
) VALUES (
arg01_USERNAME,
arg03_WIFI_SSID,
arg04_WIFI_PASSWORD
)
ON DUPLICATE KEY UPDATE
`WIFI_SSID` = arg03_WIFI_SSID,
`WIFI_PASSWORD` = arg04_WIFI_PASSWORD;
END IF $$
DELIMITER ;
I am trying to create a SQL procedure that hashes password inputs. This code won't run and I am not getting any useful response errors.
The first part creates the table, the second creates the procedure. When I call on my procedure in the third part it send the values into the procedure. There the password is supposed to be hashed using SHA2_512 and inserted into the table we made eralier.
I used online research to make this code, the parts I don't get is:
The N before my values
The SetNoCount
The #responsemessage
-- makes Admin table
CREATE TABLE IF NOT EXISTS `AdminUser` (
`AdminID` smallint(6) NOT NULL AUTO_INCREMENT,
`Username` char(15) NOT NULL,
`PasswordHash` BINARY(64) NOT NULL,
`Fornavn` char(30) NOT NULL,
`Etternavn` char(40) NOT NULL,
`Email` char(40) NOT NULL,
PRIMARY KEY (`AdminID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Makes hashing procedure
CREATE OR REPLACE PROCEDURE vm_ski.addAdmin
#pUsername NVARCHAR(50),
#pPassword NVARCHAR(50),
#pFornavn NVARCHAR(30),
#pEtternavn NVARCHAR(40),
#pEmail NVARCHAR(40),
#responseMessage NVARCHAR(250)='' OUTPUT
AS
BEGIN
SET NOCOUNT ON
BEGIN TRY
INSERT INTO vm_ski.AdminUser (Username, PasswordHash, Fornavn, Etternavn, Email)
VALUES(#pUsername, HASHBYTES('SHA2_512', #pPassword), #pFornavn, #pEtternavn, #pEmail)
SET #responseMessage='Success'
END TRY
BEGIN CATCH
SET #responseMessage=ERROR_MESSAGE()
END CATCH
END;
-- Admin example
DECLARE #responseMessage NVARCHAR(250)
EXECUTE vm_ski.addAdmin
#pUsername = N'sondre',
#pPassword = N'example'
#pFornavn = N'Sondre'
#pEtternavn = N'Morgendal'
#pEmail = N'sondre.example#gmail.com'
;
This is not a direct answer to the question; this is a security note on the methodology of the question
Do NOT hash passwords in MySQL. The data given to MySQL is plaintext, and easily intercepted by MySQL processing logs as well as possibly numerous other places before being dumped in the database (such as if message packets sent to the database are non-localhost and are non-TLS). ( Why? )
When hashing passwords you want to be doing so as early in the process as possible. This typically means using PHP password_hash and simply dumping only the hashed data in the MySQL.
If you do not use PHP to interact with your SQL then you can use other server methods such as Argon2 or Libsodium.
Also as a side point you should be using the mb4 UTF-8 charset and collations - principly utf8mb4_general_ci ( Why? )
I'm a noob im MYSQL and I'm trying to make a trigger who will auto-fill 2 fields(customername, customersurname) in an invoice table. Can anyoane explain me please what I do wrong in that trigger? Thank you very much! :)
CREATE TABLE customer(
customerID INT(6) PRIMARY KEY AUTO_INCREMENT,
customername VARCHAR(20) NOT NULL,
customersurname VARCHAR(20) NOT NULL,
customeraddress VARCHAR(200)
);
CREATE TABLE invoice(
invoiceID INT (6) Primary KEY AUTO_INCREMENT,
customerID INT (6) REFERENCES customer(customerID),
customername VARCHAR(20) REFERENCES customer(customername),
invoicedate DATE,
orderID INT(6) REFERENCES orders(orderID),
products VARCHAR(200) REFERENCES orderlines(productname),
FOREIGN KEY(orderID) REFERENCES orders(orderID)
);
CREATE TRIGGER autofill_invoice BEFORE INSERT ON invoice FOR EACH ROW
BEGIN
IF (new.customerID = customer.customerID,
new.customersurname = customer.customersurname )
THEN
SET new.customername = customer.customername,
new.customersurname = customer.customersurname;
END IF;
END;
As mysql documentation on defining stored programs explains:
If you use the mysql client program to define a stored program containing semicolon characters, a problem arises. By default, mysql itself recognizes the semicolon as a statement delimiter, so you must redefine the delimiter temporarily to cause mysql to pass the entire stored program definition to the server.
To redefine the mysql delimiter, use the delimiter command. The
following example shows how to do this for the dorepeat() procedure
just shown. The delimiter is changed to // to enable the entire
definition to be passed to the server as a single statement, and then
restored to ; before invoking the procedure. This enables the ;
delimiter used in the procedure body to be passed through to the
server rather than being interpreted by mysql itself.
So, use the delimiter command when you define the stored procedure:
DELIMITER //
CREATE TRIGGER autofill_invoice BEFORE INSERT ON invoice FOR EACH ROW
BEGIN
IF (new.customerID = customer.customerID,
new.customersurname = customer.customersurname )
THEN
SET new.customername = customer.customername,
new.customersurname = customer.customersurname;
END IF;
END//
DELIMITER ;
Next time pls provide exact error description in your question!
My application is logging the details of every http request in several MySQL tables via a stored procedure which is returning a unique request id to the application.
CALL http_req('ip', 'url', 'method', 'timestamp', #error, #request_id);
Now I also want to log all http request headers into a table, each header in a seperate row:
CREATE TABLE `http_header` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`request_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`value` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
PRIMARY KEY (`id`))
The problem is that each client has a different number and types of headers. I have not found a way to pass all header details to my stored procedure and then insert them into the above table.
Currently I have to generate and execute a second insert query from my application after the stored procedure call to save the headers:
INSERT INTO http_header (request_id, name, value)
VALUES (20153, 'cache-control', 'max-age=0'),
(20153, 'accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'),
(20153, 'accept-encoding', 'gzip,deflate,sdch');
Is is possible save the second query and insert the headers from inside the stored procedure? Like passing all headers as a single string and parse it inside the stored procedure?
Yes, it is possible. MySQL does support sufficient flow control structures (REPEAT, IF) and string processing (LOCATE(), SUBSTRING()) to allow splitting the header strings in the database. Here is a very simplistic example:
CREATE PROCEDURE http_req(IN ip CHAR(12), IN url VARCHAR(512), IN method CHAR(8), IN ts DATETIME, IN headers TEXT, OUT err INT, OUT request_id INT)
BEGIN
DECLARE loc INT;
DECLARE hloc INT;
DECLARE hdr TEXT DEFAULT NULL;
DECLARE hval TEXT DEFAULT NULL;
DECLARE s TEXT DEFAULT NULL;
START TRANSACTION;
INSERT INTO http_requests VALUES (NULL,INET_ATON(ip), url, method, ts);
SELECT last_insert_id() INTO request_id;
REPEAT
SET loc=LOCATE("\n",headers);
IF (loc = 0) THEN
SET s=headers;
ELSE
SET s=SUBSTRING(headers,1,loc-1);
SET headers=SUBSTRING(headers,loc+1);
END IF;
SET hloc=LOCATE(':',s);
IF (hloc = 0) THEN
SET hdr=s;
SET hval='';
ELSE
SET hdr=SUBSTRING(s,1,hloc-1);
SET hval=SUBSTRING(s,hloc+1);
END IF;
INSERT INTO http_header VALUES (null,request_id,hdr,hval);
UNTIL (loc=0) END REPEAT;
COMMIT;
END
There are some obvious problems with this code; like your headers will be stored incorrectly if they contain linefeed (\n). Also there is no error management (e.g. err return value is not populated correctly; no rollback). Fixing these has been left as an exercise to the reader ;)
PhpMyAdmin doesn't accept the parameters "id_jugador_IN" inside the procedure.
This is the procedure we're executing:
SET GLOBAL event_scheduler = 1;
use traviandatabase;
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_monitoritzacio_jugador $$
CREATE PROCEDURE sp_monitoritzacio_jugador(IN id_jugador_IN INT(10))
BEGIN
CREATE OR REPLACE
VIEW dades_ususari AS
SELECT j.nom AS jugador, j.sexe AS sexe, j.edat AS edat, j.correu AS correu, a.nom AS alianca, p.nom AS pais, c.nom_ciutat AS ciutat
FROM jugador AS j
JOIN alianca AS a
JOIN pais AS p
JOIN ciutat AS c
ON j.id_jugador = id_jugador_IN
GROUP BY id_jugador_IN;
END $$
DELIMITER ;
CALL sp_monitoritzacio_jugador(1);
And this is the table "jugador":
DROP TABLE IF EXISTS `jugador`;
CREATE TABLE `jugador` (
`id_jugador` int(10) NOT NULL AUTO_INCREMENT,
`id_raca` int(10) NOT NULL,
`id_pais` int(10) NOT NULL,
`id_alianca` int(10) DEFAULT '0',
`nom` varchar(20) NOT NULL,
`sexe` enum('Home','Dona') NOT NULL,
`edat` int(10) NOT NULL,
`correu` varchar(20) NOT NULL,
PRIMARY KEY (`id_jugador`),
KEY `jugador-alianca` (`id_alianca`),
KEY `id_pais` (`id_pais`),
KEY `id_raca` (`id_raca`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
So it doesn't stop displaying the same error:
MySQL said: 1351 - View's SELECT contains a variable or parameter
As you see - view cannot use variables, it is a limitation. You are trying to create a view with exact WHERE condition; construct the CREATE VIEW statement text firstly, then use prepared statements to execute the statement, it will help you. But, do you really need it, to create, create and create new view?
EDIT: This is the content of the reference in the comment.
Olexandr Melnyk A simple workaround for MySQL's limitation on local variables usage in views is to use a function, which returns variable's value:
create function book_subject
returns varchar(64) as
return #book_subject;
create view thematical_books as
select title
, author
from books
where subject = book_subject();