SQL Emailing Different Rows to Different Email addresses - sql-server-2008

I've written a stored procedure that runs every day and finds checks we are unable to process due to insufficient information on the check. The results of this query gives me a table with 4 columns, one of which is an email address, the three other columns being check info for the unprocessed check.
CHECK_AMT | CHECK_DATE | CUSTOMER_NAME | EMAIL_ADDRESS
So each row has information for a different check and or different customer. I want SQL to send an email to Mr/s. [EMAIL_ADDRESS] at each company [COMPANY_NAME] notifying them that they need to contact us regarding a check dated [CHECK_DATE] for $[CHECK_AMT]. Each customer can only receive an email the information for their own check, not the entire table that is being produced by the stored procedure.
I've looked at other SQL generated emails, but havent found one that sends emails this way. Any guidance on emailing information from row1 to the email address in row1, info from row2 to the email address in row2...etc.? I've only been working with sql for about 3 weeks now, so I'm still very new to everything. If anyone has any questions, I'll be happy to answer them. Thank you!

DECLARE
#ch_amt DECIMAL(20,2),
#ch_date DATE,
#c_name NVARCHAR(255),
#email VARCHAR(320),
#msg NVARCHAR(MAX);
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
SELECT CHECK_AMT, CHECK_DATE, CUSTOMER_NAME, EMAIL_ADDRESS
FROM dbo.SomeTable
WHERE [some clause that lets you know this check was nOt processed];
OPEN c;
FETCH c INTO #ch_amt, #ch_date, #c_name, #email;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #msg = N'Dear ' + #c_name + ', we could not process your check...';
EXEC msdb.dbo.sp_send_dbmail
#recipients = #email,
#subject = N'Check processing failure',
#body = #msg;
FETCH c INTO #ch_amt, #ch_date, #c_name, #email;
END
CLOSE c;
DEALLOCATE c;
This assumes Database Mail is configured and that you want to send the mail from the default profile. See the documentation for sp_send_dbmail for more info.

I'm thinking you just need a loop of some kind. Either a cursor, or a while loop, maybe something like:
declare #check_id int;
declare #email varchar(100);
declare #check_date date;
...etc...
while exists (select 1 from emails where ... and msg_sent = 0)
begin
select top 1 #check_id = check_id, #email = email, #check_date = check_date, ...
from emails
where ... and msg_sent = 0;
' Now you've got variables which you can use to send your email
update emails set msg_sent = 1
where check_id = #check_id;
end;
You can probably clean up the loop a bit to avoid doubling up the queries, but you get the idea...

Related

MYSQL execute stored procedure in if statement or run complicated SET statement

I've got a table where the credits and debits switch when being imported occasionally - so I've got some code to set a variable and then swap if it matches, however I can't get it to run in an IF statement, I've tried to put it in a stored procedure but can't run the stored procedure in an IF statement either. What would you recommend? see below for code. thanks
set #TotalCr = (select max(TotalCredit) from mbs_headers);
If (#TotalCr = (select sum(PDebit) from mbs_details) and #TotalCr =! (select sum(PCredit) from mbs_details))
then UPDATE mbs_detailstest SET PCredit=#tmp:=PCredit, PCredit=PDebit, PDebit=#tmp
else
end;
OR
set #TotalCr = (select max(TotalCredit) from mbs_headers);
If (#TotalCr = (select sum(PDebit) from mbs_details) and #TotalCr =! (select sum(PCredit) from mbs_details))
then exec TestSwapProc
else
end;
with TestSwapProc containing only
UPDATE mbs_detailstest SET PCredit=#tmp:=PCredit, PCredit=PDebit, PDebit=#tmp
sample data -
table: details
Name, Credit, Debit
Mike, 100, 20
Mike, 10, 0
Table: headers
name, totalcredits, totaldebits
Mike, 20, 110
I need the Details table switched around to reflect the true value as it sometimes gets inserted in the wrong way
desired results:
Table: Details
Name, Credits, Debits
Mike, 20, 100
Mike, 0, 10
Headers table to stay the same, as it is always correct
You can do something like this:
declare v_total decimal(10,2);
declare v_debit decimal(10,2);
declare v_credit decimal(10,2);
select max(TotalCredit) into v_total
from mbs_headers;
select sum(PDebit), sum(PCredit) into v_debit, v_credit
from mbs_details;
If (v_total = v_debit and v_total != v_credit) then
UPDATE mbs_detailstest
SET PCredit=v_debit, PDebit=v_credit;
end if;

Stored Procedure to send different email content to different contacts when it is 30 days before the finish date

I need to create a stored procedure in my ms sql server management studio 2008 to send automated email to each email address in the table when it is 30 days before the 'finish date' showing the 'data' value of the same row as the email content. Sample table is as below. I am new to stored procedure, can you please help me with this? Thanks in advance.
So this query picks out the data you want:
SELECT email, data
FROM YourTable
WHERE [finish date] = DATEADD(d,-30,CAST(GETDATE() AS DATE))
Here is a stored procedure that uses a cursor to go through those one by one and send an email. Run this in management studio to create the stored procedure.
After that use uspSendEmails to run it.
You can use a SQL Agent job to run this every day.
CREATE PROC uspSendEmails
BEGIN
-- variables to hold values for each row
DECLARE #email VARCHAR(50)
DECLARE #data VARCHAR(50)
-- declare the cursor
DECLARE cEmails CURSOR FOR
SELECT email, data
FROM YourTable
WHERE [finish date] = DATEADD(d,-30,CAST(GETDATE() AS DATE))
-- Open the cursor and fetch first row
OPEN cEmails
FETCH NEXT FROM cEmails
INTO #email, #data
WHILE ##FETCH_STATUS = 0
BEGIN
-- Use database mail SP to send email
EXEC sp_send_dbmail
#profile_name = 'Your mail profile',
#recipients = #email,
#subject = 'subject'
#body=#data
-- Get the next row
FETCH NEXT FROM cEmails
INTO #email, #data
END
CLOSE cEmails
DEALLOCATE cEmails
END

MySQL Stored Procedure Search another table

I am totally new to Stored Procedures, but know that this could be more efficient than trying to write PHP+MySQL code each time I need to do something like this.
I have two tables. CapitalAssets, Systems
I want find all CapitalAssets.ServerName that are not null
I have to link the two tables together, the Systems table has IP addresses, hostname.
I want to (row-by-row) grab CapitalAssets.ServerName and search Systems.hostname, IF it is found I want to link/print
CapitalAssests: Systems.id, Systems.hostname, Systems.IP, CapitalAssets.id, CapitalAssets.ServerName
Here is my start to my stored procedure, It is wrong. I do not now how to pass the Systems.hostname to do the search (where the ? is)
begin
declare GSATcur cursor for
'select id,NEName,ManagementAddress FROM GSAT WHERE NEName like ?';
declare CapitalCurr CURSOR FOR
'SELECT id,SystemName FROM CapitalAssets WHERE SystemName != ""';
DECLARE start INT DEFAULT 0;
DECLARE sysname_not_found BOOL DEFAULT FALSE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET sysname_not_found = TRUE;
OPEN GSATcur;
OPEN CapitalCur;
loop1:
WHILE start < 5 do
FETCH SystemName INTO NEName;
IF sysname_not_found THEN
LEAVE loop1;
END IF;
END WHILE;
CLOSE CapitalCur;
CLOSE GSATcur;
END;
The two tables are in the same dB.
" grab CapitalAssets.ServerName and search Systems.hostname, IF it is found I want to link/print "
If this is the ultimate goal. Try this
SELECT * FROM Systems
WHERE hostname IN ( SELECT DISTINCT(ServerName)
FROM CapitalAssets WHERE ServerName IS NOT NULL );
UPDATE CapitalAssets
INNER JOIN Systems
ON Systems.hostname = CapitalAssests.ServerName
SET CapitalAssets.ipAddress = Systems.ipAddress;
UPDATE CapitalAssets
SET ipAddress = ( SELECT ipAddress
FROM Systems
WHERE Systems.hostname = CapitalAssests.ServerName );

MySQL 1329 Error No Data - Zero rows fetched

I have searched SO, for similar and I found one other posting similar to this and I followed what I thought was the follow up but I'm still seeing a problem.
I have also been sifting through the MySQL manuals, and what I have here looks like it is correct.
DELIMITER $$
CREATE DEFINER=`perimUser`#`localhost` PROCEDURE `assignLOBId`()
BEGIN
declare id, done INT default 0;
declare name VarChar(45);
declare lobCursor Cursor for Select idLineOfBusiness as id, name from LineOfBusiness;
declare continue handler for not found set done = 1;
OPEN lobCursor;
my_loop: LOOP
FETCH lobCursor INTO id, name;
IF done = 1 THEN
CLOSE lobCursor;
LEAVE my_loop;
END IF;
insert into test values (id, name);
UPDATE medium set idLOB = id where LOB = name;
UPDATE low set idLOB = id where LOB = name;
End LOOP my_loop;
END
I have run the Query that I"m using for the cursor and it does return 13 rows. Tables medium and low are full of data about 600 rows in each. the LOB match values in the LOB column of each. The values that were used to create the ones in lineofbusiness were generated from medium and low.
The goal here is to use this pattern a number of times as I work to normalized the data in medium and low. Otherwise I'd take the short cut and create a bunch of manual update statements.
I'm not too sure why your cursor isn't working as expected (you don't say whether your test table is populated with the results that you expect?), but it appears to me your procedure is simply implementing a multiple-table UPDATE (so can probably be entirely replaced with the following):
UPDATE LineOfBusiness
LEFT JOIN medium ON LineOfBusiness.name = medium.LOB
LEFT JOIN low ON LineOfBusiness.name = low.LOB
SET medium.idLOB = LineOfBusiness.idLineOfBusiness
, low.idLOB = LineOfBusiness.idLineOfBusiness

Having issues on a validation for email on a table

What i'm trying to do is to validate the email of a certain register on a trigger. For example if a customer is registered for the first time it should create an email with both first and last name (example: user.last#email.com) however if there's already a register with the same name it should create the email the same way with the first and last name following the customer_id (example: user.last2#email.com).
The code that i have so far is the following:
delimiter $
create trigger before_customer_insert
before insert on customer
for each row
begin
declare emailVal varchar(45);
declare checkData int;
declare checkData2 int;
set checkData = (select count(first_name) from customer where first_name = new.first_name);
set checkData2 = (select count(last_name) from customer where last_name = new.last_name);
if((checkData = 1) and (checkData2 = 1)) then
set new.email = (concat(new.first_name,'.', new.last_name, '#sakilacustomer.org'));
else
set new.email = (concat(new.first_name,'.', new.last_name, new.customer_id, '#sakilacustomer.oeg'));
end if;
if(new.kind_customer is null) then
set new.kind_customer = '1';
end if;
set new.active = 1;
end $
The problem that i'm having is that when it's the first register it inserts the email but with a 0 for example "name.last0#email.com" and if i try and insert with the same information shows the same email. I tried to change the logic in the if statements but still showed the same issues.
Your logic is backward. You have:
if((checkData = 1) and (checkData2 = 1)) then
But you want:
if((checkData = 0) and (checkData2 = 0)) then
You want to use the name without a customer ID when there AREN'T any existing records in the database with those names.
Note I'm not sure your check of looking for first names and last names separately is quite what you want. Wouldn't you want to check if the whole address is found as-is?
The way it's written, if someone named Joe Bloggs tries to join, he'll be joe.bloggs1 if there's anybody else named Joe in the system, even if there is no other Joe Bloggs.