How to create random numbers at set time interval in mysql? - mysql

I want to insert random numbers between 23 and 31 at every 5 seconds in a Mysql table.
I know that I have to use RAND() function. But i don't know how to use it for inserting random numbers at set time interval.

You can use the event scheduler for this:
create table foo (id int primary key auto_increment, value int);
create event insert_random_value_every_5_sec on schedule every 5 second do insert into foo (value) select floor(23+rand()*9) as value;
If the event scheduler is disabled, you will need to enable it:
set global event_scheduler=on;
You can specify start and or end times for the event in the create event statement or later in alter event.

This will give you random numbers FLOOR(RAND()*(31-23+1))+23 And this will give you data in every 5 second date MOD(SECOND(curdate()) ,5)=0. You can use this sql -
SELECT
FLOOR(RAND()*(31-23+1))+23
FROM table
WHERE MOD(SECOND(curdate()) ,5)=0

Alternatively, you can use PHP file and using script timeInterval with AJAX to insert the random value to the database. I will tell you step by step but without code.
Steps:
create PHP function to connect your database (you can Googling with keysearch mysqli_connect)
create PHP function to handle your AJAX request and save it in database (keysearch: mysqli_query)
create script function (ex: named ajax_query) to send AJAX request with RAND function to generate random number as you wish. (You can read this question)
create script interval function to call function "ajax_query"
PS: don't forget to include/use jQuery library in your file

Related

Selecting Into Lag (Window Function) in MySQL Stored Function

I am trying to automate mathematic formulas that I need to run many times over a dataset for a view page. I have used the SELECT INTO function to successfully create these values. Below is an example of code that has worked:
DELIMITER //
DROP FUNCTION IF EXISTS InvLevel;
CREATE FUNCTION InvLevel(
metric DECIMAL (65,4),
norm DECIMAL (65,10)
)
RETURNS DECIMAL(65,4)
BEGIN
SET #InvLevel = NULL;
SELECT
metric * norm
INTO #InvLevel;
RETURN #InvLevel;
END //
I then call this with:
CREATE VIEW Mainfile
SELECT
Clients, Users, Normalization, ID, Year
MNorm(Clients, Normalization) AS ClientsN,
MNorm(Users, Normalization) AS UsersN
FROM Dataset
Does everything I want! I'm happy.
However, one of the important functions I need to run is a lag function--i.e. I'm interested in how clients, users, etc. has changed over time. So I wrote the following stored function:
DELIMITER //
DROP FUNCTION IF EXISTS Pace;
CREATE FUNCTION Pace(
metric decimal(65,4),
id VARCHAR(20),
year INT
)
RETURNS DECIMAL(65,4)
BEGIN
SELECT
metric - (LAG(metric, 1) OVER (PARTITION BY id ORDER BY year))
INTO #paceco;
RETURN #paceco;
END //
That I then call as:
Pace(Clients,ID,Year) AS ClientsP
However, this operation only returns NULL values in ClientsP. I know it's not a question of the formula since if I directly write out the math in the create view function, I receive the correct values.
I know that I can just plug the original math into the view function but I have many metrics I will be repeating this formula on (for the next few years or so) so I would vastly prefer to automate it instead of have long, messy SQL files. Thanks in advance.

Examining jsonb object values in trigger WHEN clause

I have a trigger in postgresql 12 that fires like so:
WHEN (OLD.some_jsonb_object_column IS DISTINCT FROM NEW.some_jsonb_object_column)
I would like to only run this trigger when values have changed, and not run them if only keys have changed. In this use case, it can be guaranteed that we are not adding and removing keys at the same time. I do not know what the object keys will be ahead of time, so I cannot get the values via ->>.
I have tried something akin to:
WHEN (jsonb_each(OLD.some_jsonb_object_column) IS DISTINCT FROM jsonb_each(NEW.some_jsonb_object_column))
which results in the error:
set-returning functions are not allowed in trigger WHEN conditions
Is there a way to get the values of a jsonb object without using a set-returning function?
To test if a new key has been added:
key_added := EXISTS (SELECT *
FROM json_object_keys(NEW.some_jsonb_object_column) AS n
EXCEPT
SELECT *
FROM json_object_keys(OLD.some_jsonb_object_column) AS o
);
Similarly, you can check if a key was removed.
That should solve your problem.

Is there a way to change the default date input format

I have a source of data from where I extract some fields, among the fields there are some date fields and the source sends their values like this
#DD/MM/YYYY#
almost all the fields can be sent into the query with no modificaction, except this of course.
I have written a program the gets the data from an internet connection and sends it to the MySQL server and it's sending everything as it should, I am sure because I enabled general logging in the MySQL server and I can see all the queries are correct, except the ones with date fields.
I would like to avoid parsing the fields this way because it's a lot of work since it's all written in c, but if there is no way to do it, I understand and would accept that as an answer of course.
As an example suppose we had the following
INSERT INTO sometable VALUES ('#12/10/2015#', ... OTHER_VALUES ..., '#11/10/2015#');
in this case I send the whole thing as a query using mysql_query() from libmysqlclient.
In other cases I can split the parts of the message in something that is like an instruction and the parameters, something like this
iab A,B,C,#12/10/2015#,X,Y,#11/10/2015#
which could mean INSERT INTO table_a_something_b_whatever VALUES, and in this situation of course, I capture all the parameters and send a single query with a list of VALUES in it. Also in this situation, it's rather simple because I can handle the date like this
char date[] = "#11/10/2015#";
int day;
int month;
int year;
if (sscanf(date, "#%d/%d/%d#", &day, &month, &year) == 3)
{
/* it's fine, build a sane YYYY-MM-DD */
}
So the question is:
How can I tell the MySQL server in what format the date fields are?
Clarification to: Comment 1
Not necessarily INSERT, it's more complex than that. They are sometimes queries with all their parameters in it, sometimes they are just the parameters and I have to build the query. It's a huge mess but I can't do anything about it because it's a paid database and I must use it for the time being.
The real problem is when the query comes from the source and has to be sent as it is, because then there can be many occurrences. When I split the parameters one by one there is no real problem because parsing the above date format and generating the appropriate value of MySQL is quite simple.
You can use STR_TO_DATE() in MySQL:
SELECT STR_TO_DATE('#08/10/2015#','#%d/%m%Y#');
Use this as part of your INSERT process:
INSERT INTO yourtable (yourdatecolumn) VALUES (STR_TO_DATE('#08/10/2015#','#%d/%m%Y#'));
The only Thing I could imagine at the Moment would be to Change your Column-Type from DateTime to varchar and use a BEFORE INSERT Trigger to fix "wrong" Dates.
Something like this:
DELIMITER //
CREATE TRIGGER t1 BEFORE INSERT on myTable FOR EACH ROW
BEGIN
IF (NEW.myDate regexp '#[[:digit:]]+\/[[:digit:]]+\/[[:digit:]]+#') THEN
SET NEW.myDate = STR_TO_DATE(NEW.myDate,'#%d/%m/%Y#');
END IF;
END; //
DELIMITER ;
If you are just Need to run the Import in question once, use the Trigger to generate a "proper" dateTimeColumn out of the inserts - and drop the varchar-column afterwards:
('myDate' := varchar column to be dropped afterwards;`'myRealDate' := DateTime Column to Keep afterwards)
DELIMITER //
CREATE TRIGGER t1 BEFORE INSERT on myTable FOR EACH ROW
BEGIN
IF (NEW.myDate regexp '#[[:digit:]]+\/[[:digit:]]+\/[[:digit:]]+#') THEN
SET NEW.myRealDate = STR_TO_DATE(NEW.myDate,'#%d/%m/%Y#');
else
#assume a valid date representation
SET NEW.myRealDate = NEW.myDate;
END IF;
END; //
DELIMITER ;
Unfortunately you cannot use a Trigger to work on the datetime-column itself, because mysql will already mess up the NEW.myDate-Column.

How does UDF in MySQL work internally and the reason behind the time difference between the two methods available

There are two ways in creating an UDF
a) By using a CREATE FUNCTION syntax which directly creates a function in that particular database.
Eg:
http://www.sqlexamples.info/PHP/mysql_udf1.htm
b) By writing a C code, compiling it and using its .so library file and linking it to the mysql server and then creating a function in mysql
Eg:
http://blog.loftdigital.com/blog/how-to-write-mysql-functions-in-c
In the first method (a),
CREATE FUNCTION `func`(variable INT) RETURNS int(11)
DETERMINISTIC
BEGIN
RETURN variable
END
it takes about 12 seconds to return the data for a select query like
select fiscal(col1) from table;
where
select col1 from table;
takes only about 0.42 seconds!!
where as the same written in C code takes only around 0.64 seconds!
I wanted to know what is that that is causing this time difference for a simple return function with no processing done in it. Also wanted to know how mySql allocates memory to these two different methods.

Unique fields on mySQL table - generating promo codes

I am developing a PHP script and I have a table like this:
TABLE_CODE
code varchar 8
name varchar 30
this code column has to be a code using random letters from A to Z and characters from 0 to 9 and has to be unique. all uppercase. Something like
A4RTX33Z
I have create a method to generate this code using PHP. But this is a intensive task because I have to query the database to see if the generated code is unique before proceeding and the table may have a lot of records.
Because I know mySQL is a bag of tricks but not having advanced knowledge about it now, I wonder if there's some mechanism that could be built in a table to run a script (or something) every time a new record in created on that table to fill the code column with a unique value.
thanks
edit: What I wonder is if there's a way to created the code on-the-fly, as the record is being added to the table and that code being unique.
Better generate these codes in SQL. This is 8-character random "Promo code generator":
INSERT IGNORE INTO
TABLE_CODE(name, code)
VALUES(
UPPER(SUBSTRING(MD5(RAND()) FROM 1 FOR 8)), -- random 8 characters fixed length
'your code name'
)
Add UNIQUE on code field as #JW suggested, and some error-handling in PHP, because sometimes generated value may be not UNIQUE, and MySQL will raise error in that situation.
Adding a UNIQUE constraint on the code column is the first thing you would need to do. Then, to insert the code I would write a small loop like this:
// INSERT IGNORE will not generate an error if the code already exists
// rather, the affected rows will be 0.
$stmt = $db->prepare('INSERT IGNORE INTO table_code (code, name) VALUES (?, ?)');
$name = 'whatever name';
do {
$code = func_to_generate_code();
$stmt->execute(array($code, $name));
} while (!$stmt->rowCount()); // repeat until at least one row affected
As the table grows the number of loops may increase, so if you feel it should only try three times, you could add it as a loop condition and throw an error if that happens.
Btw, I would suggest using transactions to make sure if an error occurs after the code generation, rolling back will make sure the code is removed (can be reused).