mysql test IF variable IS NULL (or empty) - mysql

we are selecting a row in mysql/mariadb and storing chosen columns in variables. After this, using IF we would like to test one of the variables and see if it has been set or is null, if it is then we assign it a value and continue on.
Using IS NULL does not seem to work on a non expression.
select id,history,active,jsonorder
INTO #id,#history,#active,#jsonorder
from myTable where uid = myUid
delimiter |
IF #jsonorder IS NULL THEN
#myNewVal="zzz";
ELSE
#myNewVal="yyy";
END IF|
insert into otherTable (colA) VALUES (#myNewVar);
What is the correct way to test if the select has provided a value into a variable such as #jsonorder?

We could use an expression in the SELECT list:
SELECT t.id
, t.history
, t.active
, IFNULL(t.order,1) AS `order`
INTO #id
, #history
, #active
, #order
FROM `myTable` t
WHERE t.uid = ...
Note that DELIMITER is not a SQL statement; it's command recognized by the mysql command line client (and some other clients).
documented here in MySQL Reference Manual: https://dev.mysql.com/doc/refman/8.0/en/mysql-commands.html
It's not clear in what context this script is being run; is this part of a MySQL stored program, or being called application code. What we are actually trying to achieve?
There are several other expressions we could use in the SELECT list, e.g.
CASE WHEN t.order IS NULL THEN 1 ELSE t.order END`
or
IF(t.order IS NULL,1,t.order)
et al.
FOLLOWUP
If we don't want to modify the original SQL statement; if we execute this:
SELECT t.id
, t.history
, t.active
, t.jsonorder
INTO #id
, #history
, #active
, #jsonorder
FROM `myTable` t
WHERE t.uid = ...
And then we want to perform an assignment to another user defined variable, based on a conditional test, we can achieve that in another SELECT or a SET statement.
For example:
SELECT #myNewVal := IF(#jsonorder IS NULL,'zzz','yyy') ;
ELSE 'yyy'
-or-
SELECT CASE
WHEN #jsonorder IS NULL
THEN 'zzz'
ELSE 'yyy'
END
INTO #myNewVal
-or-
SET #myNewVal := IF(#jsonorder IS NULL,'zzz','yyy')

The IF statement can only be used in Stored Routines. The IF function can be used virtually anywhere an expression can be put:
select id,history,active,jsonorder
INTO #id,#history,#active,#jsonorder
from myTable
where uid = myUid;
insert into otherTable (colA)
VALUES (IF(#jsonorder IS NULL, "zzz", "yyy"));
Where does myUid come from?
Is otherTable only one column wide? Or do all the other columns have defaults?
(I'm worried that you over-sanitized the question.)

This solve for cases where order is null, but not for when myUid doesnt exist in your table
SELECT id,history,active, COALESCE(order,1)
INTO #id,#history,#active,#order
FROM myTable
WHERE uid = myUid

Related

Why does a MySql query, valid in Workbench, return syntax errors in phpmyadmin?

so i have 2 tables as table1 and table2 in 2 different databases as id_information and id_information_backup. Both the tables have the following columns: (id bigint, name varchar, surname varchar) I made this trigger where when the user enters name and surname in table1 , it calculates the ascii code of it and do some calculations and store it in the "name" column of the second table which is "table2". All of these has been done in Mysql workbench. when i import the code into phpmyadmin then it gives me too many syntax errors. I tried to figure what syntax errors do i have but i could not find. I am sharing the trigger below. Kindly help me if you can. I will really appreciate it. I guess it is because of the version that i used is MySQL workbench 8.0 and the version that i am importing this into is PHPmyadmin 4.9.4 . Fix the problem if you can please.
delimiter $$
CREATE DEFINER = CURRENT_USER TRIGGER `id_information`.`table1_after_INSERT1` AFTER INSERT ON `table1` FOR EACH ROW
BEGIN
declare p , r , copy, result, result1 decimal(64,0);
declare name1, surnam varchar(15);
declare a int;
set name1 = new.name;
set surnam = new.surname;
set a= 100;
set result =0;
set copy = 0;
set result1 =0;
set p =0 ;
set r =0 ;
with recursive cte as (
select name1 as name1, left(name1, 1) as val, 1 as idx
union all
select name1, substring(name1, idx + 1, 1), idx + 1
from cte
where idx < char_length(name1)
)
select group_concat(ascii(val) + a order by idx separator '') ascii_word from cte into result;
with recursive ctee as (
select surnam as surnam, left(surnam, 1) as vall , 1 as idxx
union all
select surnam, substring(surnam, idxx+ 1, 1), idxx+ 1
from ctee
where idxx< char_length(surnam)
)
select group_concat(ascii(vall ) + a order by idxx separator '') ascii_word from ctee into result1;
select group_concat(result, result1) into copy;
insert into id_information_backup.table2 set table2.name = copy;
END$$
delimiter ;
When you try to run the command (by pressing the "Go" button at the bottom of the SQL text area), what happens?
If phpMyAdmin is showing the errors as red circles with a white x to the left of the SQL area before submitting, then these are syntax warnings that won't affect your ability to submit the query. These are provided as hints by the SQL linter in phpMyAdmin.
phpMyAdmin syntax warning:
If the errors come after submitting the statements, then the errors come from MySQL itself and aren't directly caused by phpMyAdmin.
MySQL syntax error:
In PHPMyAdmin you need to set up delimiter in a small box under the main query
It should be signed as "Delimiter" ;-)
I ended getting caught by that one a few time :-D

Is it possible that I could find a row contains a string? Assume that I do not know which columns contain a string

I know that there are several ways to find which row's column contains a string, like using [column name] regexp ' ' or [column name] like ' '
while currently what I need some help is I have a table with several columns, all of there are varchar or text and I am not sure which column contains a certain string. Just say that I want to search a "xxx from a table. Several different columns could contain this string or not. Is there a way that I could find which column contains this string?
I have a thinking and the solution could be
select * from [table name] where [column1] regexp 'xxx' or
[column2] regexp 'xxx' or ...... [column39] regexp 'xxx' or .....
[colum60] regexp 'xxx' or ... or [column 80] regexp 'xxx';
I do not want the query like this. Is there another effective way?
To give a better example, say that we are searching for a table that belongs to a blog.
We have title, URL, content, key words, tag, comment and so on. Now we just say, if any blog article is related to "database-normalization", this word may appear in the title, URL or content or anywhere, and I do not want to write it one by one like
where title regexp 'database-normalization' or content regexp 'database-normalization' or url regexp 'database-normalization'......
as when there are hundreds columns, I need to write a hundred, or in this case is there an effective way instead of write hundred or statement? Like using if-else or collections or some others to build the query.
If you want a pure dynamic way, you can try this. I've tried it long back on sql-server and hope it may help you.
#TMP_TABLE -- a temporary table
- PK, IDENTITY
- TABLE_NAME
- COLUMN_NAME
- IS_EXIST
INSERT INTO #TMP_TABLE (TABLE_NAME,COLUMN_NAME)
SELECT C.TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_NAME = <your-table> AND C.DATA_TYPE = 'varchar'; -- you can modify it to handle multiple table at once.
-- boundaries
SET #MINID = (SELECT ISNULL(MIN(<PK>),0) FROM #TMP_TABLE );
SET #MAXID = (SELECT ISNULL(MAX(<PK>),0) FROM #TMP_TABLE );
WHILE ((#MINID<=#MAXID) AND (#MINID<>0))
BEGIN
SELECT #TABLE_NAME = TABLE_NAME,#COLUMN_NAME = COLUMN_NAME
FROM #TMP_TABLE
WHERE <PK> = #MINID;
SET #sqlString = ' UPDATE #TMP_TABLE
SET IS_EXIST = 1
WHERE EXIST (SELECT 1 FROM '+ #TABLE_NAME+' WHERE '+ #COLUMN_NAME +' = ''demo.webstater.com'') AND <PK> = '+ #MINID;
EXEC(#sql) ;
SET #MINID = (SELECT MIN(<PK>) FROM #TMP_TABLE WHERE <PK> > #MINID );
END
SELECT * FROM #TMP_TABLE WHERE IS_EXIST = 1 ; -- will give you matched results.
If you know the columns in advance, what you proposed is probably the most effective way (if a little verbose).
Otherwise, you could get the column names from INFORMATION_SCHEMA.COLUMNS and construct dynamic SQL based on that.
His question is not to query specific columns with like clause. He has been asking to apply same pattern across columns dynamically.
Example: Table having 3 columns - FirstName, LastName, Address and pattern matching is "starts with A" then resulting query should be:
Select * From Customer where FirstName like 'A%" or LastName like 'A%" or Address like 'A%'
If you want to build query in business layer, this could easily be done with reflection along with EF.
If you are motivated to do in database then you can achieve by building query dynamically and then execute through sp_executesql.
Try this (Just pass tablename and the string to be find)-:
create proc usp_findString
#tablename varchar(500),
#string varchar(max)
as
Begin
Declare #sql2 varchar(max),#sql nvarchar(max)
SELECT #sql2=
STUFF((SELECT ', case when '+QUOTENAME(NAME)+'='''+#string+''' then 1 else 0 end as '+NAME
FROM (select a.name from sys.columns a join sys.tables b on a.[object_id]=b.[object_id] where b.name=#tablename) T1
--WHERE T1.ID=T2.ID
FOR XML PATH('')),1,1,'')
--print #string
set #sql='select '+#sql2+' from '+#tablename
print #sql
EXEC sp_executesql #sql
End
SQL Server 2014
One way is to use CASE to check the substring existence with LOCATE in mysql and return the column but all you have to check in every column of the table as below:
CREATE TABLE test(col1 VARCHAR(1000), col2 VARCHAR(1000), col3 VARCHAR(1000))
INSERT INTO test VALUES
('while currently what I need some help is I have a table with 10 columns',
'contains a certain string. Just say that I want to search a table',
'contains a certain string demo.webstater.com')
SELECT (CASE WHEN LOCATE('demo.webstater.com', col1, 1) > 0 THEN 'col1'
WHEN LOCATE('demo.webstater.com', col2, 1) > 0 THEN 'col2'
WHEN LOCATE('demo.webstater.com', col3, 1) > 0 THEN 'col3'
END) whichColumn
FROM test
OUTPUT:
whichColumn
col3
There are many ways in which you can do your analysis. You can use "LIKE A%%" if it starts from A in SQL, "REGEX" LibrarY for multiple checks.

Mysql Using a variable within a case statement

Trying to do something very simple.
Want to Run a SP that checks if one of the arguments is null. If so, store an empty string in a log table, otherwise store the value.
CREATE DEFINER=`root`#`localhost` PROCEDURE `SP_TestVariable`(
Code1 varchar(255) ,
CodeToTest varchar(255)
)
BEGIN
CASE
WHEN CodeToTest IS NULL THEN
set #FinalCode = ' '
ELSE
set #FinalCode = CodeToTest
end
-- Now do the insert into the log table
INSERT INTO `TempLogTable` ( strField1, strField2)
VALUES (Code1 , #FinalCode );
You can reduce all that to a simle query
INSERT INTO `TempLogTable` (strField1, strField2)
SELECT Code1, coalesce(CodeToTest, '')
and for that I would even drop the procedure and just use the query instead.

Add ELSE in SELECT statement MySQL

So what Im trying is to add ELSE or the kind of condition that adds the exeception to the current rule. I have this before insert trigger right now:
SET new.perfId = (SELECT cust.webId FROM cust where cust.regTime=new.regTime);
I would like to add an ELSE to that statement, something like:
SET new.perfId = (SELECT cust.webId FROM cust where cust.regTime=new.regTime) ELSE blabla
How should this be set in order query is correct?
Thank you.
If you mean, that your condition is that the select doesn't return null, you can use coalesce().
SET new.perfId = COALESCE((SELECT cust.webId FROM cust where cust.regTime=new.regTime), 'blabla');
COALESCE() returns the first of its parameters which isn't NULL.
You could use COALESCE:
From the docs:
Returns the first non-NULL value in the list, or NULL if there are no
non-NULL values.
mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL
You would end up with:
SET new.perfId = (SELECT COALESCE(cust.webId,"BLABLA")
FROM cust where cust.regTime=new.regTime);

MySql Stored Proc - Select query returns null if using where clause not included in select list?

I have a proc that simply contains the following:
SELECT Col1, Col2 FROM table WHERE Id = 1;
This always returns null values. If I change the statement to:
SELECT Id, Col1, Cold2 FROM table WHERE Id = 1;
The row gets returned as expected. Does mySql procs demand that the where clause columns appear in the select list? It doesn't have this behaviour when running the SQL directly in phpMyAdmin.
Here's the code in question:
CREATE PROCEDURE sp_player_login
(
IN
userGraphId INT(11),
authToken TEXT
)
BEGIN
DECLARE playerId INT;
DECLARE newPlayer BOOLEAN DEFAULT FALSE;
SELECT Id INTO playerId FROM player WHERE FacebookGraphId = userGraphId;
If playerId IS NULL THEN
-- Create the player.
SET newPlayer = TRUE;
-- Get new player defaults.
SELECT NewPlayerTurns, NewPlayerMoney, NewPlayerMorale, NewPlayerMissilePower FROM defaults WHERE Id = 1;
END IF;
END #
The second SELECT NewPlayerTurns... is the one that returns null values if I don't specify the Id column in the select clause. If I remove the first SELECT Id INTO ...the second query works without the Id in the select clause...? confused