Send e-mail when a row changes - sql-server-2008-express

I will try to best explain what I would like to do (for simplicity I only included two columns that I am working with):
I have two different tables, dbo.device and dbo.devicestatus.
They are both tied by DeviceDN which is primary key.
On dbo.devicestatus, there are two columns called TonerLowB and TonerLowY that can have a value of either 1 or 0.
What I would like to do is have the application (SQLExpress 2008) send an e-mail when one of the rows of TonerLowB or TonerLowY has it's value updated to "1", but not when it has it's value updated to "0" and have that row "merged" with the data from dbo.device.
What I managed to do so far is combine the data from dbo.device with the data from dbo.devicestatus and show just values that are greater than 0 as a select statement:
`
select d.DeviceDN, s.TonerLowB, s.TonerLowY
from dbo.Device d,
dbo.DeviceStatus s
where
d.DeviceDN = s.DeviceDN
and s.TonerLowB + s.TonerLowY > 0 ;
`
I then tinkered with sp_send_dbmail to see if I can send the results via mail and I did manage to do that after defining a profile and creating myself a test mail server. I used the following command:
`
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'MyMailProfile',
#recipients = 'alex#testing.ro',
#query = 'select d.DeviceDN, s.TonerLowB, s.TonerLowY
from dbo.Device d,
dbo.DeviceStatus s
where
d.DeviceDN = s.DeviceDN
and s.TonerLowB + s.TonerLowY > 0 ;' ,
#subject = 'Your Query Results',
#attach_query_result_as_file = 1 ,
#query_result_separator = '|' ;
`
The problem is that this sends me all the lines that have a value greater than 1 and I don't know how to send for each update and just for the updated row instead of this "bulk" method.
I am thinking of adding two new columns to the database db.devicestatus, TonerLowB_LastUpdate and TonerLowY_LastUpdate, both set up as "datetime".
Then I wanted to create two triggers that would update TonerLowB_LastUpdate or TonerLowY_LastUpdate with "set gettime()" when TonerLowB or TonerLowY updates it's value and also send an e-mail with the line that changed it's value (using the mail procedure I mentioned above), if that date is older than 3 days.
Unfortunately I don't know how to declare this trigger and this is what I am trying to find help on.
Would this be possible and if so, would it be a good (reliable) mechanism?

A wise way would be use 'Triggers' in this context.
Take a look at this post to get started on this
Using Triggers to do actions after specific values are updated
To summarize, define an update trigger on the field:
CREATE TRIGGER TonerValueChanged
ON DeviceStatus
AFTER UPDATE
AS
BEGIN
// here you need to check for the condition if the value is updated to 1 and send the mail
END
Now on every value updated, based on your condition, the mail will be triggered
for every row update.
Hope this helps.

Related

find diffrences between 2 tables sql and how can i get the changed value?

i have this query
insert into changes (id_registro)
select d2.id_registro
from daily2 d2
where exists (
select 1
from daily d1
where
d1.id_registro = d2.id_registro
and (d2.origen, d2.sector, d2.entidad_um, d2.sexo, d2.entidad_nac, d2.entidad_res,
d2.municipio_res, d2.tipo_paciente,d2.fecha_ingreso, d2.fecha_sintomas,
d2.fecha_def, d2.intubado, d2.neumonia, d2.edad, d2.nacionalidad, d2.embarazo,
d2.habla_lengua_indig, d2.diabetes, d2.epoc, d2.asma, d2.inmusupr, d2.hipertension,
d2.otra_com, d2.cardiovascular, d2.obesidad,
d2.renal_cronica, d2.tabaquismo, d2.otro_caso, d2.resultado, d2.migrante,
d2.pais_nacionalidad, d2.pais_origen, d2.uci )
<>
(d1.origen, d1.sector, d1.entidad_um, d1.sexo, d1.entidad_nac, d1.entidad_res,
d1.municipio_res, d1.tipo_paciente, d1.fecha_ingreso, d1.fecha_sintomas,
d1.fecha_def, d1.intubado, d1.neumonia, d1.edad, d1.nacionalidad, d1.embarazo,
d1.habla_lengua_indig, d1.diabetes, d1.epoc, d1.asma, d1.inmusupr, d1.hipertension,
d1.otra_com, d1.cardiovascular, d1.obesidad,
d1.renal_cronica, d1.tabaquismo, d1.otro_caso, d1.resultado, d1.migrante,
d1.pais_nacionalidad, d1.pais_origen, d1.uci ))
it results in an insersion data that doesn't exist in another table, that's fine. but i want know exactly which field has changed to store it in a log table
You don't mention precisely what you expect to see in your output but basically to accomplish what you're after you'll need a long sequence of CASE clauses, one for each column
e.g. one approach might be to create a comma-separated list of the column names that have changed:
INSERT INTO changes (id_registro, column_diffs)
SELECT d2.id_registro,
CONCAT(
CASE WHEN d1.origen <> d2.origen THEN 'Origen,' ELSE '' END,
CASE WHEN d1.sector <> d2.sector THEN 'Sector,' ELSE '' END,
etc.
Within the THEN part of the CASE you can build whatever detail you want to show
e.g. a string showing before and after values of the columns CONCAT('Origen: Was==> ', d1.origen, ' Now==>', d2.origen). Presumably though you'll also need to record the times of these changes if there can be multiple updates to the same record throughout the day.
Essentially you'll need to decide what information you want to show in your logfile, but based on your example query you should have all the information you need.

UPDATE QUERY - Sum up a value from form with value from table

I've just started using microsoft access so I don't really know how to solve this. I would like to use an update query to add a value from a form to a value on a table.
I originally used the SUM expression which gave me an error saying it was an aggregate function.
I also tried to add the two values together (e.g [field1] + [field2]) which as a result gave me a value with both numbers together instead of adding them together.
The following is the SQL I'm using:
UPDATE Votes
SET Votes.NumVotes = [Votes]![NumVotes]+[Forms]![frmVote]![txtnumvotes]
WHERE (((Votes.ActID) = [Forms]![frmVote]![combacts])
AND ((Votes.RoundNum) = [Forms]![frmVote]![combrndnum]))
I want to add a value [txtnumvotes] a form to a field [NumVotes] from the table [Votes].
Could someone please help me?
You can specify the expected data type with parameters:
PARAMETERS
[Forms]![frmVote]![txtnumvotes] Short,
[Forms]![frmVote]![combacts] Long,
[Forms]![frmVote]![combrndnum] Long;
UPDATE
Votes
SET
Votes.NumVotes = [Votes]![NumVotes]+[Forms]![frmVote]![txtnumvotes]
WHERE
(((Votes.ActID) = [Forms]![frmVote]![combacts])
AND
((Votes.RoundNum) = [Forms]![frmVote]![combrndnum]))
Without the specification, Access has to guess, and that sometimes fails.

CDbCommand::createCommand() returns zero affected rows inside migration

This code works just fine (all database items updated as expected):
foreach($idMap as $menuId=>$pageId)
{
$sql = "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
$affectedRows = Yii::app()->db->createCommand($sql)->execute();
echo $affectedRows." affected rows\n";
}
But it prints 0 affected rows for each executed query. Why?
The same effect is, when executing many rows affecting statements in one SQL query:
$sql = '';
foreach($idMap as $menuId=>$pageId)
{
$sql .= "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
}
$affectedRows = Yii::app()->db->createCommand($sql)->execute();
echo $affectedRows." affected rows\n";
What am I missing? Docs says, that CDbCommand::execute should return number of rows affected by the execution. Does this feature work, when used inside migration?
CDbCommand::execute returns the row Count from underlying PDO interface, PDOstatement::rowCount only returns the row count of the last statement.
I had tested this within migration to be sure that migrate script is not running any other commands for cleanup etc, this is not the case, I am able to get correct row values from within and outside migration as well.
The most likely reason you are getting 0 as the value is because of the update command did not affect any rows ( i.e. the link values were already set to the correct values), UPDATE will return 0 if no change has occurred.
Perhaps you already run the migration on your test db and migrated down to test it few more times, however during the subsequent passes no update actually happened.
Note in the second scenario only the count of the last command ( a single row update will be shown even if update changes the table as PDOstatement::rowCount only returns the count for last statement executed.

How do I update multiple sets procedure

I've having problem with regular expression for updating the multiple set for email that doesn't work at all. You see I'm trying to update from.
alisonsmith#gmail.com
bobgraves#hotmail.com
smithers#yahoo.com
011013092949#msn.ca
011513025559#aol.ca
101513025559#MSN.COM
To the result should look like this:
alisonsmith#dony.com
bobgraves#dony.com
smithers#dony.com
011013092949#dony.com
011513025559#dony.com
101513025559#dony.com
I've tried that update procedure like this and it didn't work at all:
update dony_membership
set Email = LEFT(Email,12)+'#dony.com'
set Email = LEFT(Email,0)+'#dony.com'
where Email LIKE '%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]#%'
or Email LIKE'#%'
As it seems like you want to change the part after the #-sign for all rows I wouldn't bother with regular expressions but rather just keep what ever comes before the #-sign and append the new domain (dony.com) to it:
update dony_membership
set email = left(email, charindex('#', email, 0)) + 'dony.com'
Sample SQL Fiddle for your viewing pleasure :)

sql to set an xml value

I'm a novice in mySql.
I'm trying to replace a value in the xml column of my table.
my select method works.
SELECT * FROM `comics` WHERE ExtractValue(xml,'comic/pageNumber') = 6
my replace method doesn't. I've been searching for the correct syntax for a bit now...
SET xml.modify(
replace value of ('comic/pageNumber') with 5
)
some background:
this situation comes up when i delete a comic page.
it leaves a gap in the page numbers, after which i would either:
iterate through all the comics and remove any gaps in the page numbers.
or
iterate through all comics with pageNumber larger than the deleted page, and reduce their pageNumber by 1.
How about
UPDATE comics
SET xml = UpdateXML(xml,'comic/pageNumber', '<pageNumber>5</pageNumber>')
WHERE ExtractValue(xml,'comic/pageNumber') = 6
Tested on MySQL version 5.1
UPDATE `comics`
SET xml = UpdateXML(xml,
'comic/pageNumber',
concat('<pageNumber>',(ExtractValue(xml,'comic/pageNumber')+1),'</pageNumber>'))
WHERE ExtractValue(xml,'comic/pageNumber') >= 1
You'd be better off actually storing the fields in the table, rather than a single field with xml in it. Then the following would work. Otherwise there's not much point using a relational database at all.
BEGIN;
DELETE FROM `comics`
WHERE `comicID` = :id AND `pageNumber` = :page;
UPDATE `comics` SET `pageNumber` = `pageNumber` - 1
WHERE `comicID` = :id AND `pageNumber` > :page;
COMMIT;