My stored procedure always returns 0. I tried unique data and duplicated but the insert is done with success but the return value is always the same #new_identity = 0
CREATE PROCEDURE [dbo].[spAddAuthor]
#Author tyAuthor READONLY,
#new_identity INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- check if the author exists
IF NOT EXISTS (SELECT Id_Author FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
BEGIN
INSERT INTO dbo.Authors (Username, sexe, email, phone, address)
SELECT [Username], [sexe], [email], [phone], [address]
FROM #Author
-- output the new row
SELECT #new_identity = ##IDENTITY;
END
ELSE
BEGIN
-- get the author Id if already exists
SELECT #new_identity = (SELECT TOP 1 Id_Author
FROM dbo.Authors
WHERE (dbo.Authors.Username = (SELECT Username FROM #Author)
OR dbo.Authors.phone = (SELECT phone FROM #Author)
OR dbo.Authors.email = (SELECT email FROM #Author)))
END
END
I found that in the declaration of the parameters I put null beside the output and that what caused the problem.
#new_identity INT = NULL OUTPUT
but I don't understand why, I thought the 'null' was like the default value, or when you try to make the parameter optional you add null as default value.
can someone explain, please?
I have written the below mentioned procedure in MySQL.
CREATE DEFINER=`root`#`localhost` PROCEDURE `IsUploaderLoggedIn`(
IN `inMobile` CHAR(10),
IN `inSessionID` varchar(34)
)
BEGIN
DECLARE isLoggedIn TINYINT(1) DEFAULT 0;
DECLARE uploaderType VARCHAR(10) DEFAULT '';
CALL GetUploaderType(inMobile, #x);
SELECT #x INTO uploaderType;
IF uploaderType = "surveyor" THEN
SELECT Count(*) INTO isLoggedIn FROM surveyors WHERE Mobile = inMobile AND SessionID = inSessionID;
SELECT "surveyor";
ELSE
SELECT Count(*) INTO isLoggedIn FROM uploaders WHERE Mobile = inMobile AND SessionID = inSessionID;
SELECT "uploader";
END IF;
SELECT isLoggedIn;
END;
On executing the procedure in Navicat, for a given value of inMobile and inSessionID, the values returned are:
Result 1: usertype | surveyor
Result 1(2): uploader | uploader
Result 1(3): 0 or 1 as the case may be
Where as, the value of Result 1(2)s should have been surveyor | surveyor.
Below is definition of stored procedure GetUploaderType:
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetUploaderType`(
IN `inMobile` CHAR(10),
OUT `Usertype` VARCHAR(8)
)
BEGIN
DECLARE usertype VARCHAR(8) DEFAULT '';
DECLARE userExists TINYINT DEFAULT 0;
/*SET officeExists = 0;*/
/* Check if mobile number belongs to a surveyor */
SELECT Count(*) INTO userExists FROM surveyors WHERE Mobile = inMobile;
IF userExists = 1 THEN
SET usertype = 'surveyor';
ELSE
/* If user is not surveyor, check for it in uploaders */
SELECT Count(*) INTO userExists FROM uploaders WHERE Mobile = inMobile;
IF userExists = 1 THEN
SET usertype = 'uploader';
END IF;
END IF;
SELECT usertype;
END
What is wrong with my script please?
In GetUploaderType, you redeclared the variable Usertype, thus hiding the (different) out-variable of the same name, see scope:
The scope of a local variable is the BEGIN ... END block within which it is declared. The variable can be referred to in blocks nested within the declaring block, except those blocks that declare a variable with the same name.
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**')
CREATE OR REPLACE TRIGGER ATTENDANCE_NOTIFY AFTER INSERT OR UPDATE ON ATTENDANCE
FOR EACH ROW
DECLARE
V_STUDENT_ID STUDENT.STUDENT_ID%TYPE := NULL;
V_HOD_ID HEAD_OF_DEPARTMENT.HOD_ID%TYPE := NULL;
V_SUBCODE STUDENT.SUBCODE%TYPE := NULL;
V_ATTENDANCE ATTENDENCE%TYPE := NULL;
BEGIN
SELECT SUB_CODE, SUB_NAME INTO V_SUB_CODE, FROM SUBJECT WHERE STUDENT_ID = :NEW.STUDENT_ID;
SELECT STUDENT_ID INTO V_STUDENT_ID FROM STUDENT WHERE SUBJECT_CODE = :NEW.SUBJECT_CODE;
SELECT HOD_ID INTO V_HOD_ID FROM STUDENT_HOD WHERE STUDENT_ID = :NEW.STUDENT_ID;
SELECT ATTENDENCE INTO V_ATTENDENCE FROM ATTENDENCE WHERE STUDENT_ID=:NEW_STUDENT_ID
IF (V_ATTENDENCE IS NOT NULL AND V_SUB_CODE IS NOT NULL AND V_STUDENT_ID IS NOT NULL AND V_HOD_ID IS NOT NULL) THEN
IF (:NEW.ATTENDENCE < (V_ATTENDENCE * 0.85)) THEN
INSERT INTO NOTIFY VALUES(V_HOD_ID, V_STUDENT_ID || ' (ID:- ' || :NEW.STUDENT_ID ||') HAS LESS THAN 85% ATTENDENCE IN SUBJECT ' || V_SUB_CODE);
END IF;
END IF;
EXCEPTION
WHEN OTHERS
THEN NULL;
END;
i am getting a syntax error in declare
There is no way to refer datatype of column in MySQL. DECLARE must statically declare a variable's type and size.
Something like
DECLARE myvar VARCHAR( 8 ) -- This is valid in Mysql
Not
DECLARE myvar mytable.myfield%TYPE --This is invalid in Mysql
Hope this helps.
I have an InnoDB table with a unique index on performance_id, ticket_rank_id and ticket_type_id.
All of these id's have relations to other tables, but their values can also be NULL.
MySQL allows duplicate rows if one of the column values is NULL so I decided to build a trigger for this problem.
CREATE TRIGGER `before_insert_performance_tickets`
BEFORE INSERT ON `performance_tickets` FOR EACH ROW BEGIN
DECLARE num_rows INTEGER;
SELECT COUNT(*) INTO num_rows FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND ticket_rank_id = NEW.ticket_rank_id
AND ticket_type_id = NEW.ticket_type_id;
IF num_rows > 0 THEN
// Cancel insert action
ELSE
// Perform insert action
END IF;
END
The problem is AND ticket_rank_id = NEW.ticket_rank_id where I have to check if ticket_rank_id is NULL or has a value.
AND ticket_rank_id = NULL does not work, it only works if i do AND ticket_rank_id IS NULL.
Is there any slick solution for this or do I have to write separate queries depending on NEW.ticket_rank_id and NEW.ticket_type_id being NULL or not?
You need to add extra OR condition for NULL values (ticket_rank_id IS NULL OR ticket_rank_id = NEW.ticket_rank_id) because NULL compared with anything return FALSE. Try this query:
SELECT COUNT(*)
INTO num_rows
FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND (ticket_rank_id IS NULL OR ticket_rank_id = NEW.ticket_rank_id)
AND (ticket_type_id IS NULL OR ticket_type_id = NEW.ticket_type_id);
I think I figured it out:
SELECT COUNT(*) INTO num_rows FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND IF(NEW.ticket_rank_id IS NULL, ticket_rank_id IS NULL, ticket_rank_id = NEW.ticket_rank_id)
AND IF(NEW.ticket_type_id IS NULL, ticket_type_id IS NULL, ticket_type_id = NEW.ticket_type_id)
Seems to work, now I have to figure out how to abort the insert if num_rows == 1. But that's a different problem.
Thanks anyways ;)