Why "drop procedure if exists konami" not working in mysql? - mysql

I write a mysql script , it works fine :
use cloud_fight;
drop procedure if exists `konami`;
drop function if exists `rand_string`;
delimiter //
CREATE FUNCTION `rand_string`(n INT) RETURNS varchar(255)
BEGIN
DECLARE chars_str varchar(255) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789rew';
DECLARE return_str varchar(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
while i < n do
SET return_str = concat(return_str,substring(chars_str , FLOOR(1 + RAND()*64 ),1));
SET i = i + 1;
END while;
RETURN return_str;
END //
delimiter $$
create procedure konami()
begin
declare q int default 1;
while q<=2 DO
set #N=rand_string(64);
insert into fight_user (user_guid , first_name , last_name , user_name , nick_name , gender , city , province , country , head_img_url , created_at , last_updated) values (#N, '' , '' , '' , rand_string(5) , '2' , 'bj' , 'bj' , 'cn' , '' , now() , now());
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'WECHAT_UNIONID' , now() , now() , 1 from fight_user where user_guid = #N;
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'MP_OPENID' , now() , now() , 1 from fight_user where user_guid = #N;
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'PA_OPENID' , now() , now() , 1 from fight_user where user_guid = #N;
set q=q+1;
end while;
end $$
call konami();
But when I move the command " drop procedure if exists konami " to the front of procedure konami() as shown below:
drop function if exists `rand_string`;
delimiter //
CREATE FUNCTION `rand_string`(n INT) RETURNS varchar(255)
BEGIN
DECLARE chars_str varchar(255) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789rew';
DECLARE return_str varchar(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
while i < n do
SET return_str = concat(return_str,substring(chars_str , FLOOR(1 + RAND()*64 ),1));
SET i = i + 1;
END while;
RETURN return_str;
END //
drop procedure if exists `konami`;
delimiter $$
create procedure konami()
begin
declare q int default 1;
while q<=2 DO
set #N=rand_string(64);
insert into fight_user (user_guid , first_name , last_name , user_name , nick_name , gender , city , province , country , head_img_url , created_at , last_updated) values (#N, '' , '' , '' , rand_string(5) , '2' , 'bj' , 'bj' , 'cn' , '' , now() , now());
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'WECHAT_UNIONID' , now() , now() , 1 from fight_user where user_guid = #N;
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'MP_OPENID' , now() , now() , 1 from fight_user where user_guid = #N;
insert into fight_user_cake (fight_user_id , t_id , third_party_user_id , type , created_at , last_updated , status) select id , '2' , rand_string(20) , 'PA_OPENID' , now() , now() , 1 from fight_user where user_guid = #N;
set q=q+1;
end while;
end $$
call konami();
When I run the second script in mysql workbench 6.3.
It report error : Error Code: 1304. PROCEDURE konami already exists
So my question is when I move the command " drop procedure if exists konami " to the front of procedure konami() , why is this statement "drop procedure if exists konami" not working ?

Since you changed to DELIMITER // you need to use that delimiter at the end of each statement until you change it back.
DROP PROCEDURE and CREATE PROCEDURE are separate statements, and each requires its own statement delimiter.
DROP PROCEDURE IF EXISTS konami //

Related

Count vowels and consonants in an array

I am trying to write a function which will return number of vowels
and consonants. Using the IF statement function will successfully
compile, however when I call it in the select it shows the message :
"Conversion failed when converting the varchar value 'MAMAMIA' to
data type int."`
I tried with the CASE statement, but there are too many syntax
errors and i think it is not the best method of solving the problem
using CASE ...
CREATE FUNCTION VOW_CONS(#ARRAY VARCHAR(20))
RETURNS INT
BEGIN
DECLARE #COUNTT INT;
DECLARE #COUNTT1 INT;
SET #COUNTT=0;
SET #COUNTT1=0;
WHILE (#ARRAY!=0)
BEGIN
IF(#ARRAY LIKE '[aeiouAEIOU]%')
SET #COUNTT=#COUNTT+1
ELSE SET #COUNTT1=#COUNTT1+1
/*
DECLARE #C INT;
SET #C=(CASE #SIR WHEN 'A' THEN #COUNTT=#COUNTT+1;
WHEN 'E' THEN #COUNTT=#COUNTT+1
WHEN 'I' THEN #COUNTT=#COUNTT+1
WHEN 'O' THEN #COUNTT=#COUNTT+1
WHEN 'U' THEN #COUNTT=#COUNTT+1
WHEN 'A' THEN #COUNTT=#COUNTT+1
WHEN ' ' THEN ' '
ELSE #COUNTT1=#COUNTT1+1
END)
*/
END
RETURN #COUNTT;
END
SELECT DBO.VOW_CONS('MAMAMIA')
Without knowing what version of SQL Server you are using, I am going to assume you are using the latest version, meaning you have access to TRANSLATE. Also I'm going to assume you do need access to both the number of vowels and consonants, so a table-value function seems the better method here. As such, you could do something like this:
CREATE FUNCTION dbo.CountVowelsAndConsonants (#String varchar(20))
RETURNS table
AS RETURN
SELECT DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'aeiou','|||||'),'|','')) AS Vowels, --Pipe is a character that can't be in your string
DATALENGTH(#String) - DATALENGTH(REPLACE(TRANSLATE(#String,'bcdfghjklmnpqrstvwxyz','|||||||||||||||||||||'),'|','')) AS Consonants --Pipe is a character that can't be in your string
GO
And then you can use the function like so:
SELECT *
FROM (VALUES('MAMAMIA'),('Knowledge is power'))V(YourString)
CROSS APPLY dbo.CountVowelsAndConsonents(V.YourString);
Another option would be to split the string into its individual letters using a tally table, join that to a table of vowels/consonants and then get your counts.
Here is a working example, you'll have to update/change for your specific needs but should give you an idea on how it works.
DECLARE #string NVARCHAR(100)
SET #string = 'Knowledge is power';
--Here we build a table of all the letters setting a flag on which ones are vowels
DECLARE #VowelConsonants TABLE
(
[Letter] CHAR(1)
, [IsVowel] BIT
);
--We load it with the data
INSERT INTO #VowelConsonants (
[Letter]
, [IsVowel]
)
VALUES ( 'a', 1 ) , ( 'b', 0 ) , ( 'c', 0 ) , ( 'd', 0 ) , ( 'e', 1 ) , ( 'f', 0 ) , ( 'g', 0 ) , ( 'h', 0 ) , ( 'i', 1 ) , ( 'j', 0 ) , ( 'k', 0 ) , ( 'l', 0 ) , ( 'm', 0 ) , ( 'n', 0 ) , ( 'o', 1 ) , ( 'p', 0 ) , ( 'q', 0 ) , ( 'r', 0 ) , ( 's', 0 ) , ( 't', 0 ) , ( 'u', 1 ) , ( 'v', 0 ) , ( 'w', 0 ) , ( 'x', 0 ) , ( 'y', 0 ) , ( 'z', 0 );
--This tally table example gives 10,000 numbers
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
SELECT SUM( CASE WHEN [vc].[IsVowel] = 1 THEN 1
ELSE 0
END
) AS [VowelCount]
, SUM( CASE WHEN [vc].[IsVowel] = 0 THEN 1
ELSE 0
END
) AS [ConsonantCount]
FROM [cteTally] [t] --Select from tally cte
INNER JOIN #VowelConsonants [vc] --Join to VowelConsonants table on the letter.
ON LOWER([vc].[Letter]) = LOWER(SUBSTRING(#string, [t].[N], 1)) --Using the number from the tally table we can easily split out each letter using substring
WHERE [t].[N] <= LEN(#string);
Giving you results of:
VowelCount ConsonantCount
----------- --------------
6 10

Alternate for Indexing

We need result from Table based on datetime filter. But it working slow in mysql. I can't implement indexing on date & timestamp columns due to it will slow our insertion/updation. So can you please suggest any alternate for select the data quickly based on date and datetime filter with better performance.
SQL Query :
SELECT *
FROM (
SELECT id
, title
, language
, lang_code
, financial
, fname
, lname
, mname
, mname_br
, suffix
, CASE WHEN DOB='0000-00-00' THEN NULL ELSE DOB END AS DOB
, street
, street2
, postal_code
, zip_ext
, city
, state
, country_code
, phone_home
, phone_biz
, phone_biz_ext
, phone_contact
, phone_cell
, status
, CASE WHEN date='0000-00-00 00:00:00' THEN NULL ELSE
CAST(date as datetime) END AS date
, sex
, referrer
, referrerID
, providerID
, ethnoracial
, pid
, temp_key
, primary_care
, default_facility
, created_by
, patientStatus
, primary_care_id
, Sec_HCFA
, noBalanceBill
, erx_entry
, erx_patient_id
, athenaID
, CASE WHEN licenseDate='0000-00-00 00:00:00' THEN NULL ELSE licenseDate end as licenseDate
, race
, otherRace
, ethnicity
, otherEthnicity
, primary_care_phy_name
, primary_care_phy_id
, CASE WHEN dod_patient='0000-00-00' THEN NULL ELSE dod_patient END AS dod_patient--
, locked--
, co_man_phy--
, co_man_phy_id--
, vip--
, External_MRN_1--
, External_MRN_2--
, External_MRN_3--
, External_MRN_4
, as_id
, CASE WHEN acc_statement_date='0000-00-00' THEN acc_statement_date END AS acc_statement_date
, CASE WHEN timestamp='0000-00-00 00:00:00' THEN NULL ELSE timestamp END AS timestamp
, api_id
, fmh_pt_status
, race_code
, ethnicity_code
, patient_payer
, CASE WHEN date='0000-00-00 00:00:00' THEN NULL ELSE date END AS transfer_created
,CASE WHEN timestamp='0000-00-00 00:00:00' THEN NULL ELSE timestamp END AS transfer_updated
,CASE WHEN date > '2020-11-10 00:00:00' THEN 'new' ELSE 'changed' END AS flagfield
,CASE WHEN date='0000-00-00 00:00:00' THEN NULL ELSE date END AS sortdate
FROM patient_data
WHERE (date > '2020-11-10 00:00:00' or timestamp > '2019-04-01 19:53:57-04')
AND month(date) > 0)t
ORDER BY flagfield desc,
sortdate;
)
id Column has indexing in the table
Get rid of
SELECT *
FROM (
)t
it adds nothing, except to slow things down.
Let's focus on
SELECT id
FROM patient_data
WHERE (date > '2020-11-10 00:00:00'
or timestamp > '2019-04-01 19:53:57-04')
AND month(date) > 0
Does that shortened query run "too slow"? If not, then we can use that as a derived table to see if that will speed it up. If so, then we will need to get into UNION and indexing.

output sql data to html with hyperlink

I have below query that converts sql result to HTML
DECLARE #BODY VARCHAR(MAX)
SET #BODY = CAST((
SELECT td = entity + '</td><td>' + procname + '</td><td>' + exedate + '</td><td>' + rowcnt + '</td><td>' +
cont + '</td><td>' + fpath from (
SELECT entity = ENTITY , procname = PROC_NAME,exedate = EXEC_DATE, rowcnt = ROW_COUNT,
cont = CONTENT, fpath = FILEPATH FROM HTML_OUTPUTFOREMAIL) AS D
for xml path('tr'),type) as varchar(max))
set #BODY = '<tr><h1>SUMMARY TABLE</h1>'
+'<table cellpadding="2" cellspacing="2" border="1">'
+'<tr><th>ENTITY</th><th>PROC_NAME</th><th>EXEC_DATE</th><th>ROW_COUNT</th><th>CONTENT</th><th>FILEPATH</th><tr>'
+ REPLACE(replace(#body,'<','<'),'>','>')
+'<table>'
print #body
In this data I have a column "fpath" that contains link to the HTML file. But I want the result of this column in a hyperlink.
This is not really SQL Server jobs to output HTML.
If you have to create it this way, you can generate the whole table with FOR XML Explicit.
I am just creating a dummy table with 4 line here and dummy data. You still have to change columns name or add more.
declare #t table(id int, entity varchar(10), name varchar(10), fpath varchar(50), link_name varchar(10), exec_date datetime)
insert into #t(id, entity, name, fpath, link_name, exec_date) values
(1, 'ent1', 'A', 'google.com', 'linkA', '20150115')
, (2, 'ent2', 'B', 'google.com', 'linkB', '20150215')
, (3, 'ent3', 'C', 'google.com', 'linkC', '20150315')
, (4, 'ent4', 'D', 'google.com', 'linkD', '20150415')
Select Tag, Parent
, [Table] as 'Table!1!'
, [entity] as 'TR!2!TD!Element'
, [name] as 'TR!2!TD!Element'
, [exec_date] as 'TR!2!TD!Element'
, [TD] as 'TD!3!TD!Element'
, [href] as 'A!4!href'
, [target] as 'A!4!target'
, [link] as 'A!4!'
From(
Select 1 as Tag, NULL as Parent, 0 as sort
, NULL as 'Table'
, NULL as 'entity'
, NULL as 'name'
, NULL as 'exec_date'
, NULL as 'TD'
, NULL as 'href'
, NULL as 'link'
, NULL as 'Target'
Union All
Select 2 as Tag, 1 as Parent, id*10 as sort
, NULL
, entity
, name
, cast(exec_date as varchar(50))
, NULL
, NULL
, NULL
, NULL
From #t
Union All
Select 3 as Tag, 2 as Parent, id*10+1 as sort
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
From #t
Union All
Select 4 as Tag, 3 as Parent, id*10+2
, NULL
, NULL
, NULL
, NULL
, NULL
, fpath
, link_name
, '_blank'
From #t
) X
Order By sort
For XML EXplicit

Syntax Error in INSERT INTO statement, no other details given

The SQL generated my code looks like this -
INSERT INTO [Item] (
Vendor_num
, item
, [Desc]
, Pack
, item_size
, unit_of_sale
, allowance
, points
, Promo
, WS_Cost
, WS_Unit_cost
, Retailer_Price
, Retail
, Cust_Use
, Show_Price
, GP
, Min
, Max
, Book_Number
, Del1_date
, Del2_date
, Del3_date
, Del4_date
, Del5_date
, Del6_date
, Del7_date
, Del8_date
, Del9_date
, Del10_date
, Del11_date
, Del12_date
, Del13_date
, Del14_date
, Del15_date
, warehouse
, Purchase_Group
, GPM
, Material_Number
, PM
) VALUES (
'11'
, '300681'
, 'item description'
, '60'
, 'BOX'
, 'BOX'
, '3'
, '20'
, 'Y'
, '0'
, null
, '0'
, null
, '03652'
, null
, null
, null
, null
, '832'
, '6/2/2014 12:00:00 AM'
, '6/30/2014 12:00:00 AM'
, '7/28/2014 12:00:00 AM'
, '8/18/2014 12:00:00 AM'
, null
, null
, null
, null
, null
, null
, null
, null
, null
, null
, null
, '1'
, null
, null
, null
, null
)
(forgive all those null values, they're frequently not null in these inserts, so the statement needs to be flexible enough when they're not)
I'm getting a generic error --
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Syntax error in INSERT INTO statement.
The statement works fine when copied directly into a new query in Access, but when firing through .NET and OLE DB, it fails miserably.
Any ideas?
Min and Max are reserved words in Access, and should be quoted if you use them as field names or you may encounter errors;
If a reserved word is already in use, you can avoid error messages by surrounding each occurrence of the word with brackets ([ ]). However, the best solution is to change the name to a nonreserved word.
In other words, used as field names, they should be quoted as [Min] and [Max].

MySQL Trigger with multiple IF statements not working

I'm working on an 'audit_history' table that stores updates performed on my 'myTable' table. My code works with just the single IF statement that handles password updates. But as soon as I add another, I get the #1064 SQL Error. So I'm guessing it's something to do with my delimiters(?), but I just can't get it to work.
Any and all help would be great. Thanks.
IF (NEW.password <> OLD.password)
OR (NEW.password IS NOT NULL AND OLD.password IS NULL)
OR (NEW.password IS NULL AND OLD.password IS NOT NULL)
THEN
INSERT INTO myTable.audit_history
VALUES (
'update'
, NULL
, NOW()
, #user_id
, 'user'
, 'password'
, OLD.password
, NEW.password);
END IF;
IF (NEW.landline <> OLD.landline)
OR (NEW.landline IS NOT NULL AND OLD.landline IS NULL)
OR (NEW.landline IS NULL AND OLD.landline IS NOT NULL)
THEN
INSERT INTO myTable.audit_history
VALUES (
'update'
, NULL
, NOW()
, #user_id
, 'user'
, 'landline'
, OLD.landline
, NEW.landline);
END IF;
I get this error message:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to you MySQL server version for the right syntax to use near ‘IF (NEW.landline <> OLD.landline) OR (NEW.landline IS NOT NULL AND OLD.landline’ at line 17
You need BEGIN and END keywords for multiple statements
BEGIN
IF (NEW.password <> OLD.password)
OR (NEW.password IS NOT NULL AND OLD.password IS NULL)
OR (NEW.password IS NULL AND OLD.password IS NOT NULL)
THEN
INSERT INTO myTable.audit_history
VALUES (
'update'
, NULL
, NOW()
, #user_id
, 'user'
, 'password'
, OLD.password
, NEW.password);
END IF;
IF (NEW.landline <> OLD.landline)
OR (NEW.landline IS NOT NULL AND OLD.landline IS NULL)
OR (NEW.landline IS NULL AND OLD.landline IS NOT NULL)
THEN
INSERT INTO myTable.audit_history
VALUES (
'update'
, NULL
, NOW()
, #user_id
, 'user'
, 'landline'
, OLD.landline
, NEW.landline);
END IF;
END;