Related
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE J INT DEFAULT 0;
DECLARE msg varchar(255) DEFAULT null;
DECLARE msg1 varchar(255) DEFAULT null;
DECLARE s VARCHAR(255) DEFAULT null;
set i = select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
set j = (select TIMESTAMPDIFF(year,i,now()));
set msg1 = 'Congrats';
set msg = concat(msg1, j, 'Years Completed');
INSERT INTO time_line( tl_name, tl_dob, tl_message)
select em_first_name, em_DOJ, msg
from employee_master;
end
Why am I getting errors for this code. My intention is to transfer data from one table to another and to calculate the year at the same time. I am getting the error in this line.
set i = select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
Thanks For Solution.
You don't have a WHERE clause in the INSERT ... SELECT ... query, so it's selecting all rows from employee_master, and inserting a row into time_line for each of them with msg.
You don't need multiple queries. You should combine them all into a single SELECT so that the number of years in the message matches that employee.
INSERT INTO time_line (tl_name, tl_dob, tl_message)
SELECT em_first_name, em_DOJ,
CONCAT('Congrats on ', TIMESTAMPDIFF(year, em_DOJ, ,now()), ' Years Completed')
FROM employee_master
WHERE MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW());
You need to wrap the SELECT with braces:
set i = (select em_DOJ
from employee_master
where MONTH(em_DOJ) = MONTH(NOW()) and DAY(em_DOJ) = DAY(NOW()));
Additionally, this select does potentially return more than one result which would then cause an error.
I have a stored procedure where I'm looping through results in a cursor. The issue I'm having is the license_attributes value is always null when it shouldn't be. If I execute the select statement outside the stored procedure, or as a debug execute the select statement outside the cursor in the stored procedure, I get the results I'm expecting (not null)
This is the part of the select that is always returning null in the cursor:
(SELECT
CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
'""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
),'}}')
FROM
sf.Asset_Attribute__c
WHERE
sf.Asset_Attribute__c.Asset__c = license_id
GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`
Here is the section of the stored proc:
GETCLOUDACCOUNTS:BEGIN
DECLARE no_more_cloud_accounts_records boolean DEFAULT FALSE;
DECLARE company VARCHAR(255) DEFAULT null;
DECLARE license_status VARCHAR(50) DEFAULT null;
DECLARE license_id VARCHAR(18) DEFAULT null;
DECLARE cloud_owner_email VARCHAR(255) DEFAULT null;
DECLARE entitlement_plan VARCHAR(255) DEFAULT null;
DECLARE role VARCHAR(500) DEFAULT null;
DECLARE is_trial BOOLEAN DEFAULT false;
DECLARE license_attributes VARCHAR(2000) DEFAULT null;
DECLARE zuora_account_id VARCHAR(100) DEFAULT '';
DECLARE zuora_account_number VARCHAR(50) DEFAULT null;
DECLARE zuora_account_status VARCHAR(50) DEFAULT null;
DECLARE zuora_account_last_invoice_date DATETIME DEFAULT null;
DECLARE has_active_subscriptions BOOLEAN DEFAULT false;
DECLARE cloud_accounts_cursor CURSOR FOR
SELECT
(SELECT `sf`.`Contact`.`CompanyName__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `company`,
`sf`.`License_Key_Association__c`.`License_Key_Status__c` AS `license_status`,
`sf`.`License_Key_Association__c`.`License_Key__c` AS `license_id`,
`sf`.`Asset`.`ContactEmail__c` AS `cloud_owner_email`,
(SELECT `sf`.`Contact`.`CloudEntitlementPlan__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `entitlement_plan`,
`sf`.`License_Key_Association__c`.`Role__c` AS `role`,
IF( (SELECT `sf`.`Product2`.`IsCommercial__c` FROM `sf`.`Product2` WHERE `sf`.`Product2`.`Id`=`sf`.`Asset`.`Product2Id`) = 0,true,false ) AS `is_trial`,
(SELECT
CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
'""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
),'}}')
FROM
sf.Asset_Attribute__c
WHERE
sf.Asset_Attribute__c.Asset__c = license_id
GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`
FROM
`sf`.`License_Key_Association__c`
LEFT JOIN `sf`.`Asset`
ON `sf`.`License_Key_Association__c`.`License_Key__c` = `sf`.`Asset`.`Id`
JOIN `sf`.`Contact`
ON `sf`.`Contact`.`Id` = `sf`.`License_Key_Association__c`.`Contact__c`
WHERE
`sf`.`Contact`.`ExternalID__c`='someexternalidhere';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_cloud_accounts_records = true;
SELECT
(SELECT `sf`.`Contact`.`CompanyName__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `company`,
`sf`.`License_Key_Association__c`.`License_Key_Status__c` AS `license_status`,
`sf`.`License_Key_Association__c`.`License_Key__c` AS `license_id`,
`sf`.`Asset`.`ContactEmail__c` AS `cloud_owner_email`,
(SELECT `sf`.`Contact`.`CloudEntitlementPlan__c` FROM `sf`.`Contact` WHERE `sf`.`Asset`.`ContactId`=`sf`.`Contact`.`Id`) AS `entitlement_plan`,
`sf`.`License_Key_Association__c`.`Role__c` AS `role`,
IF( (SELECT `sf`.`Product2`.`IsCommercial__c` FROM `sf`.`Product2` WHERE `sf`.`Product2`.`Id`=`sf`.`Asset`.`Product2Id`) = 0,true,false ) AS `is_trial`,
(SELECT
CONCAT('{""',sf.Asset_Attribute__c.Type__c,'"": {',GROUP_CONCAT(
'""',sf.Asset_Attribute__c.Key__c,'"":""',LOWER(sf.Asset_Attribute__c.Value__c),'""'
),'}}')
FROM
sf.Asset_Attribute__c
WHERE
sf.Asset_Attribute__c.Asset__c = license_id
GROUP BY sf.Asset_Attribute__c.Asset__c) AS `license_attributes`
FROM
`sf`.`License_Key_Association__c`
LEFT JOIN `sf`.`Asset`
ON `sf`.`License_Key_Association__c`.`License_Key__c` = `sf`.`Asset`.`Id`
JOIN `sf`.`Contact`
ON `sf`.`Contact`.`Id` = `sf`.`License_Key_Association__c`.`Contact__c`
WHERE
`sf`.`Contact`.`ExternalID__c`=#p_externalId;
OPEN cloud_accounts_cursor;
CLOUDACCOUNTSLOOP: loop
fetch cloud_accounts_cursor into company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes;
IF is_trial = true THEN
SET has_active_subscriptions = true;
END IF;
SET zuora_account_id = `z`.`getZAccountId`(cloud_owner_email);
IF zuora_account_id IS NOT NULL THEN
SELECT `accountNumber`,`status`,`lastInvoiceDate` INTO zuora_account_number,zuora_account_status,zuora_account_last_invoice_date FROM zuora.Account WHERE id=zuora_account_id;
IF has_active_subscriptions = false THEN
SET has_active_subscriptions = (SELECT IF((SELECT COUNT(*) FROM `z`.`RatePlan`
RIGHT JOIN `z`.`ProductRatePlan` ON `z`.`RatePlan`.`productRatePlanId` = `z`.`ProductRatePlan`.`id`
LEFT JOIN `z`.`Subscription` ON `z`.`RatePlan`.`subscriptionId` = `z`.`Subscription`.`id`
WHERE
`z`.`ProductRatePlan`.`wowzaRatePlanCode__c` IN ( (SELECT `code` FROM `z`.`zCloudRatePlanCodes`) )
AND `z`.`Subscription`.`status` = 'Active'
AND `z`.`Subscription`.`accountId` = zuora_account_id ) > 0, true, false));
END IF;
END IF;
REPLACE INTO `sf`.`zCloudAccounts` (`user_email`,`company`,`license_status`,`license_id`,`cloud_owner_email`,`entitlement_plan`,`role`,`is_trial`,`attributes`,`zuora_account_id`,`zuora_account_number`,`zuora_account_status`,`zuora_account_last_invoice_date`,`has_active_subscriptions`) VALUES(#p_userEmail,company,license_status,license_id,cloud_owner_email,entitlement_plan,role,is_trial,license_attributes,zuora_account_id,zuora_account_number,zuora_account_status,zuora_account_last_invoice_date,has_active_subscriptions);
IF no_more_cloud_accounts_records THEN
CLOSE cloud_accounts_cursor;
LEAVE CLOUDACCOUNTSLOOP;
end if;
END LOOP CLOUDACCOUNTSLOOP;
END GETCLOUDACCOUNTS;
If I execute the full select stateout outside of GETCLOUDACCOUNTS block, I get the results I expect:
company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes
Test Company, Active, 02iq0000000jKgMAAU, myemail#email.com, Standard, Owner, 0, {""cloud"": {""cloud_num_247_t_streams"":""0"",""cloud_num_247_p_streams"":""0""}}
Test Company, Active, 02iq0000000xlBBAAY, otheremail#email.com, Standard, Admin;wcl_admin;wcl_support, 0, {""cloud"": {""cloud_num_247_t_streams"":""1"",""cloud_num_247_p_streams"":""1"",""test_attribute"":""true"",""api_access"":""true""}}
But the results inside the block show license_attributes as null:
company, license_status, license_id, cloud_owner_email, entitlement_plan, role, is_trial, license_attributes
Test Company, Active, 02iq0000000jKgMAAU, myemail#email.com, Standard, Owner, 0, null
Test Company, Active, 02iq0000000xlBBAAY, otheremail#email.com, Standard, Admin;wcl_admin;wcl_support, 0, null
Any help is greatly appreciated!
I suspect the issue is related to the procedure variable license_id.
The correlated subselect in the SELECT list includes
WHERE sf.Asset_Attribute__c.Asset__c = license_id
^^^^^^^^^^
Local variables take precedence over column references. Since license_id is declared as a variable within the code block,
DECLARE license_id VARCHAR(18) DEFAULT null;
the reference to license_id in the SELECT statement is a reference to that procedure variable.
Outside the code block, there likely is not a local variable named license_id. So that same SQL SELECT statement, that reference to license_id is not a reference to a variable, but a reference to a column.
I haven't traced through all of the logic, or the contents of license_id variable. But I suspect that explains the difference in the behavior observed with the statement, executed inside the code block vs outside the block.
You can COALESCE to take care of NULL values in your GROUP_CONCAT
COALESCE(`YourColumnName`,'')
You can also use a significantly different string to show you where the NULL value is coming from, so that you can then fix the query.
COALESCE(`YourColumnName`,'**UNEXPECTED NULL**')
I've managed to use EXEC sp_executesql in a one off statement to do a dynamic lookup, but am unable to adjust the code to create a function since EXEC is not allowed in functions. It works in procedures and I've managed to get output via PRINT for a single lookup by using a temporary table, but really that was just me struggling to find a workaround. Ideally I'd like to be able to create a scalar-value function.
The reason that I need a dynamic lookup is because the column name is stored in another table.
Here's a quick breakdown of the tables:
Questions:
Columns: Q_Group, Q_Nbr, Question_Desc, Data_Field
Sample data: 'R3', 5, 'Do you have any allergies?', 'TXT_04'
Responses:
Columns: Order_Nbr, Q_Group, TXT_01, TXT_02, TXT_03, TXT_04, etc.
Data: 999, 'R3', 'blah', 'blah', 'blah', 'NO'
Orders will be assigned a particular set of questions 'Q_Group' and often a particular question will be the same across various different sets of questions. The problem is that when the set/groups of questions were set up, the questions may not have been added in the same order, and thus the responses go into different columns.
So here's where I'm at...
I can get 'TXT_04' from the Data_Field column in Questions and use EXEC sp_executesql to do a lookup for a single order, but am struggling to find a way to accomplish this as a function of some sort.
DECLARE #col_name VARCHAR(6)
DECLARE #sql VARCHAR(100)
SET #col_name = SELECT Data_Field FROM QUESTIONS WHERE Q_Group = 'R3'
AND Question_Desc = 'Do you have any allergies?'
SET #sql = 'SELECT ' + #col_name + ' FROM RESPONSES WHERE Order_Nbr = 999'
EXEC sp_executesql #sql
I'm just at a loss as to how this could be incorporated into a function so that I could get responses for several orders in a result set. Any workarounds possible? Maybe I'm totally off base using EXEC sp_executesql?
Thanks.
Edit...
Okay, I've changed the title to reflect that I'm going to consider this solved with a procedure instead of a function, as it ended up getting the output that I wanted. Which was a table with all of the corresponding responses.
Here's the code that I settled on. I decided to use LIKE to match the Question_Desc instead of equals, and then included the Question_Desc in the results, so that it could be used a bit more broadly. Thankfully it's pretty quick to run currently. Although that could always change as the database grows!
CREATE PROCEDURE get_all_responses (#question_txt VARCHAR(255))
AS
DECLARE #response_col VARCHAR(35)
DECLARE #t TABLE (order_nbr int, question_txt VARCHAR(255), response_col VARCHAR(35), response VARCHAR(255))
DECLARE #i TABLE (id INT PRIMARY KEY IDENTITY(1,1), response_col VARCHAR(35))
DECLARE #u TABLE (order_nbr int, response VARCHAR(255))
DECLARE #sql VARCHAR(200)
INSERT #t
SELECT Order_Nbr, Question_Desc, Data_Field, NULL
FROM Responses
JOIN (
SELECT Q_Group, Question_Desc, Data_Field
FROM Questions
WHERE Question_Desc LIKE #question_txt
) #Q ON Q_Group = #Q.Q_Group
WHERE Q_Group <> '0'
ORDER BY Data_Field, Order_Nbr
-- Stop if no results found and return empty result set
IF (SELECT COUNT(*) FROM #t) = 0
BEGIN
SELECT order_nbr, question_txt, response FROM #t
RETURN
END
INSERT #i SELECT response_col FROM #t GROUP BY response_col
DECLARE #row_nbr int
DECLARE #last_row int
SET #row_nbr = 1
SET #last_row = (SELECT COUNT(*) FROM #i)
-- Iterate through each Data_Field found
WHILE #row_nbr <= #last_row
BEGIN
SET #response_col = (SELECT response_col FROM #i WHERE id = #row_nbr)
SET #sql = 'SELECT Order_Nbr, ' + #response_col + ' FROM Responses WHERE NullIf(' + #response_col + ','''') IS NOT NULL'
INSERT INTO #u
EXEC (#sql)
UPDATE #t
SET response = y.response
FROM #t AS x
INNER JOIN #u AS y ON x.order_nbr = y.order_nbr
SET #row_nbr = #row_nbr + 1
END
-- Remove results with no responses
DELETE FROM #t WHERE response IS NULL
SELECT order_nbr, question_txt, response FROM #t
RETURN
You will not be able to execute dynamic SQL from within a function but you could do this with a stored procedure and capture the output.
DECLARE #col_name VARCHAR(6), #param NVARCHAR(50), #myReturnValue VARCHAR(50)
SET #param = N'#result VARCHAR(50) OUTPUT'
DECLARE #sql VARCHAR(100)
SET #col_name = SELECT Data_Field FROM QUESTIONS WHERE Q_Group = 'R3'
AND Question_Desc = 'Do you have any allergies?'
SET #sql = 'SELECT #result = ' + #col_name + ' FROM RESPONSES WHERE Order_Nbr = 999'
EXEC sp_executesql #sql, #param, #result = #myReturnValue output
--manipulate value here
print #myReturnValue
You could also create a temp table and do an insert into from exec sp_executesql.
I have a stored proc that is setting one of the variables to NULL, though the query returns results.
Here is the SP:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select client_id into #CLIENT_ID3 from clients where
client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE = (select var_value from counter where var_name =
'latest_report_id_summarized' limit 1);
SELECT latest_invoice_id into #LATEST_INVOICE_ID from
SQL_AuditPro.clients where client_id = CLIENT_ID;
END
when I run the sp, then select the results :
select #CLIENT_ID3,#BEGIN_RANGE,#LATEST_INVOICE_ID;
I get :
12345,2342342234,NULL
I have also tried:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select client_id into #CLIENT_ID3 from clients
where client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE = (select var_value from counter where var_name =
'latest_report_id_summarized' limit 1);
SET #LATEST_INVOICE_ID = (SELECT latest_invoice_id from
SQL_AuditPro.clients where client_id = CLIENT_ID);
END
Same result. Obviously I don't need to SET #CLIENT_ID3 it was just in there for testing. Any ideas why this won't set the variable? When I run this query by itself I get a result, and if I run :
SELECT latest_invoice_id into #LATEST_INVOICE_ID from
SQL_AuditPro.clients where client_id = 12345;
select #LATEST_INVOICE_ID;
I get :
2342342234
I have tried declaring the variable, not declaring it, and it just seems like this variable seems to fall out of scope after the SP completes, yet the other two don't.
Thanks for any help you may be able to provide.
select client_id into #CLIENT_ID3 from clients where client_id = CLIENT_ID limit 1;
^---- missing #
SET #LATEST_INVOICE_ID = (SELECT [..snip..] where client_id = CLIENT_ID);
^--missing # as well
As written, both'll be intepreted as a self-equality test, e.g. where 1 = 1. There's no way for mysql to know that the client_id on EITHER side of the = is supposed to be the parameter you passed in to the stored proc, so both client_id will be treated as field names.
Since the second query is likely to return MULTIPLE rows of data, and you're trying to assign that result into a single variable, you'll get NULL as the result.
When you have defined arguments names to match with one or more of a table columns, then in your SQL statements you must use column qualifiers to differentiate with argument names. Otherwise, they will be treated and replaced as and by argument values;
See SQL Fiddle Example
In your case, as the condition client_id = CLIENT_ID was causing to (possibly) fetch multiple records, they are not assignable to a variable of non cursor type. Hence a NULL, the default value for user defined variables, was returned.
Change your procedure body as below:
CREATE DEFINER=`xxx`#`localhost` PROCEDURE `test`(IN CLIENT_ID INT)
BEGIN
DECLARE BEGIN_RANGE INT UNSIGNED DEFAULT 0;
select c.client_id into #CLIENT_ID3
from clients c
where c.client_id = CLIENT_ID limit 1;
SET #BEGIN_RANGE =
(select var_value
from counter
where var_name = 'latest_report_id_summarized' limit 1);
SET #LATEST_INVOICE_ID =
(SELECT c.latest_invoice_id
from SQL_AuditPro.clients c
where c.client_id = CLIENT_ID);
END
i have a stored procedure that searches like bellow:
BEGIN
#At first, Search in name of job:
(SELECT * FROM tb_job WHERE `name` LIKE '%some%' AND `name` LIKE '%thing%')
UNION
# second, search for tags:
(SELECT * FROM tb_job WHERE id IN
(
SELECT idJob FROM
(
(SELECT 2 AS priority1, COUNT(tb_job_tag.idTag) AS priority2, idJob FROM tb_job_tag WHERE idTag IN
(SELECT tb_tag.id FROM tb_tag WHERE tag LIKE '%some%' OR tag LIKE '%thing%')
GROUP BY tb_job_tag.idJob)
UNION
(SELECT 1, COUNT(tb_job_tag.idTag), idJob FROM tb_job_tag WHERE idTag IN
(SELECT tb_tag.id FROM tb_tag WHERE tag LIKE '%some%' AND tag LIKE '%thing%')
GROUP BY tb_job_tag.idJob)
)
AS t ORDER BY priority1, priority2 DESC
)
)
END
now i have 2 questions: how can i pass an array of words and separate them in mysql and use them in LIKE? second, how can i make this search better?
(i have 3table: tb_job, tb_tag, tb_job_tag that stores job's id and tag's id). thanks for your help.
/**
* http://www.aspdotnet-suresh.com/2013/07/sql-server-split-function-example-in.html
*/
CREATE FUNCTION dbo.Array(#String nvarchar(4000), #Delimiter char(1))
RETURNS #Results TABLE ([id] [bigint] IDENTITY(1,1) NOT NULL, Items nvarchar(4000))
AS
BEGIN
DECLARE #INDEX INT
DECLARE #SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
-- ERO FIRST TIME IN LOOP
SELECT #INDEX = 1
WHILE #INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT #INDEX = CHARINDEX(#Delimiter,#STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF #INDEX !=0
SELECT #SLICE = LEFT(#STRING,#INDEX - 1)
ELSE
SELECT #SLICE = #STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO #Results(Items) VALUES(#SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT #STRING = RIGHT(#STRING,LEN(#STRING) - #INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(#STRING) = 0 BREAK
END
RETURN
END
execute this function once in your database and now onward to access specific value you can write your query like below
DECLARE #VALUE VARCHAR(100);
SELECT TOP 1 #VALUE = Items FROM [dbo].[Array] ('some,thing,like,that' , ',') where id = 2
PRINT #VALUE
All you need to change is id in select statement. It'll accept only String values for now. But you can convert String to Int in SQL using CAST
I just created this function in hurry if you have any suggestions/modifications let me know...