473,883 Members | 1,750 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Trigger and Row Update Help

I have a table that matches up Securities and Exchanges. Individual
securities can belong on multiple exchanges. One of the columns, named
PrimaryExchange Flag, indicates if a particular exchange is the primary
exchange for that symbol. Each symbol can only have one primary
exchange.

I am trying to write a insert/update/delete trigger that enforces this
rule. The rules I have thought of are as follows:

Insert If new row has flag set, turn off flag for other rows for
that symbol. Otherwise, do nothing.

Update If updated row has flag set, turn off flag for other rows
for that symbol. Otherwise, set flag on first (MAX or MIN or TOP 1
???) row for that symbol.

Delete If deleted row had flag set, set flag on first row for that
symbol. Otherwise, do nothing.

My basic problem is how to do this when the trigger gets thrown for
multiple rows. (Since SQL does not throw individual triggers for each
row.)

Thanks.
Jul 20 '05 #1
8 8619
Sorry. I should have included some test code to make it easier for you.
Cutting and pasting will give you a test table and some
insert/delete/update statements.

USE tempdb
GO

DROP TABLE TestTable
GO

CREATE TABLE TestTable (
[Symbol] VARCHAR(15),
[Exchange] VARCHAR(5),
[PrimaryFlag] BIT
)
GO

INSERT INTO TestTable VALUES ('MSFT', 'XNAS', 1) -- first row - so flag
should be set
INSERT INTO TestTable VALUES ('QQQ', 'XNYS', 1) -- first row - so flag
should be set
INSERT INTO TestTable VALUES ('QQQ', 'XASE', 1) -- second row - so flag
should be set, but previous row should be unset
INSERT INTO TestTable VALUES ('MSFT', 'XASE', 0) -- second row - should
be unset for this, previous row not changed

UPDATE TestTable SET [PrimaryFlag] =1 WHERE [Symbol] = 'MSFT' AND
[Exchange] = 'XASE' -- set flag, unset first row

DELETE FROM TestTable WHERE [Symbol] = 'QQQ' AND [Exchange] = 'XASE' --
first row should be set
DELETE FROM TestTable WHERE [Symbol] = 'MSFT' AND [Exchange] = 'XASE' --
no change to flags
GO

SELECT * FROM [TestTable]

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 20 '05 #2
>> I have a table that matches up Securities and Exchanges. <<

Then let's use a meaningful names, reasonable data types, keys and
constraints even in the sample data. Are there really CHAR(15)
symbols in use today? And they vary in length, too?

There is not such thing as an ordering in an SQL database, so all that
talk about "first row", "second row" etc. is totally meaningless.
This is not a file system; all relationships are shown as values in
columns. Never write with BIT datatypes and flags. The datatype is
proprietary, and the use of flags is bad SQL programming. Let's try
again with good DDL:

CREATE TABLE SecuritiesExcha nges
(symbol CHAR(5) NOT NULL,
exchange_code CHAR(5) NOT NULL
CHECK (exchange_code IN (…)),
exch_prefer INTEGER DEFAULT 1 NOT NULL -- order them!
CHECK (exch_prefer >= 0),
PRIMARY KEY (exchange, symbol, exch_prefer));

Let (exch_prefer = 1) mark the primary exchange and re-write your
rules in stored procedures that you will use to insert/update/delete
from the table.

Insertion: If I add a new (exchange, symbol) then I have to mark it as
the primary exchange for that security or not.

BEGIN
IF @make_primary = 'N'
THEN INSERT INTO SecuritiesExcha nges
VALUES (@my_symbol, @my_exchange_co de,
(SELECT MAX(S1.exch_pre fer) + 1
FROM SecuritiesExcha nges AS S1
WHERE S1.symbol = ScuritiesExchan ges.symbol));
IF @make_primary = 'Y'
THEN BEGIN
UPDATE SecuritiesExcha nges
SET exch_prefer = exch_prefer +1
WHERE S1.symbol = ScuritiesExchan ges.symbol;
INSERT INTO SecuritiesExcha nges
VALUES @my_symbol, @my_exchange_co de, 1);
END;
ELSE PRINT 'Flag must be Y or N' END IF;
END;

Deletion: If I delete a (exchange, symbol) then I have to renumber all
of the exch_prefer values for that symbol.

BEGIN
DELETE FROM SecuritiesExcha nges
WHERE symbol = @my_symbol
AND exchange_code = @my_exchange_co de;
UPDATE SecuritiesExcha nges
SET exch_prefer
= (SELECT COUNT (S1.exch_prefer )
FROM SecuritiesExcha nges AS S1
WHERE S1.exch_prefer
<= SecuritiesExcha nges.exch_prefe r
AND S1.symbol
<= SecuritiesExcha nges.symbol)
WHERE symbol = @my_symbol;
END;

Update: If I update an existing (exchange, symbol) then I have to mark
it as the primary exchange for that security or not. I also might
want to re-order the preferences, so I'll need better specs before
doing that code. But it is all simple algebra.
Jul 20 '05 #3
Joe,

First off. Thank you for responding.

Quess I will just rattle off my questions (or answer some of yours).

1) What is wrong with my names? They sound reasonable to me. No
abbreviations and the name tells you want the column represents.

2) Yes there are variable length (and greater than) 5 character
symbols. NYSE and Amex symbols are normally 3 or less characters while
Nasdaq are 4 or 5. But NYSE symbols can also have a prefix that
indicates if it is preferred, class a or b, warrant, or some
combination of them. So a 3 character preferred class a stock would be
ABC.PRA (making 7 characters. To take this further, some foreign
exchanges do not use symbols but use what is called an ISIN number
(which is 7 characters).

3) I realize that there is no such thing as first or second row. I was
merely using those words in comments to signify a particular row being
inserted before the others. In other words, the MSFT/XNAS row was
inserted first, then the MSFT/ASE row was inserted.

4) Did not know about the BIT datatype. Good to know.

5) When you say that flags are bad SQL programming, you are talking
about true/false or yes/no types of columns? Your comment says to
order them using integer values. In my case, each symbol only has ONE
primary exchange, the rest are not. There is no preference or order to
the none primary exchanges.

6) Why code the one-and-only-one primary exchange logic in a stored
procedure as opposed to a trigger? By having it in a stored procedure
I am limited to single security inserts since cannot pass datasets as
parameters. I can also have the problem of having somebody NOT use the
SP and then I have multiple primary exchanges for a single security.

Again. Thank you for the help. Hope my ignorance does not annoy you
too much.
Jul 20 '05 #4
Jason (Ja*******@hotm ail.com) writes:
I have a table that matches up Securities and Exchanges. Individual
securities can belong on multiple exchanges. One of the columns, named
PrimaryExchange Flag, indicates if a particular exchange is the primary
exchange for that symbol. Each symbol can only have one primary
exchange.

I am trying to write a insert/update/delete trigger that enforces this
rule. The rules I have thought of are as follows:

Insert If new row has flag set, turn off flag for other rows for
that symbol. Otherwise, do nothing.

Update If updated row has flag set, turn off flag for other rows
for that symbol. Otherwise, set flag on first (MAX or MIN or TOP 1
???) row for that symbol.

Delete If deleted row had flag set, set flag on first row for that
symbol. Otherwise, do nothing.

My basic problem is how to do this when the trigger gets thrown for
multiple rows. (Since SQL does not throw individual triggers for each
row.)


The repro below includes a trigger that seems to fulfil the requirements.
To be able to determine "first row", I added an exch_no column. I also
added PRIMARY KEY and UNIQUE constraints to set the frames for what I'm
working with.

There is one potential problem: if you update PrimaryFlag for the
row with the lowest exch_no to 0 and if it was 1 before, the trigger
will flip it back to 1. This situation was not covered in your requirements.

The UPDATE statement in the trigger includes an EXISTS clause within
comments. As far as I can see, this clause is not needed from a functional
point of view. For performance, it could have. Then again, accessing
the inserted/deleted tables can be expensive, why it is often a good
idea to read them into a temp table or table variable.

Finally, if you expect one-row operations to be common, it may be a good
idea to say IF @@rowcount = 1 first in the trigger and have a special
code path for this case, as you may avoid performance problems in this
case.

Here is a script:

CREATE TABLE TestTable (
[Symbol] VARCHAR(15),
[Exchange] VARCHAR(5),
exch_no int,
[PrimaryFlag] BIT,
CONSTRAINT pk_exch PRIMARY KEY (Symbol, Exchange),
CONSTRAINT u_exch UNIQUE (Symbol, exch_no)
)
go
CREATE TRIGGER testtable_tri on TestTable FOR
INSERT, UPDATE, DELETE AS

UPDATE TestTable
SET PrimaryFlag = 0
FROM TestTable t
WHERE EXISTS (SELECT *
FROM inserted i
WHERE t.Symbol = i.Symbol
AND t.Exchange <> i.Exchange
AND i.PrimaryFlag = 1)

UPDATE TestTable
SET PrimaryFlag = 1
FROM TestTable t
JOIN (SELECT t.Symbol, exch_no = MIN(t.exch_no)
FROM TestTable t
WHERE t.PrimaryFlag = 0
AND NOT EXISTS (SELECT *
FROM TestTable t2
WHERE t2.Symbol = t.Symbol
AND t2.PrimaryFlag = 1)
GROUP BY t.Symbol) AS t3
ON t.Symbol = t3.Symbol
AND t.exch_no = t3.exch_no
/*WHERE EXISTS (SELECT *
FROM deleted d
WHERE d.Symbol = t.Symbol)*/
GO

INSERT INTO TestTable VALUES ('MSFT', 'XNAS', 1, 1)
-- first row - so flagshould be set
INSERT INTO TestTable VALUES ('QQQ', 'XNYS', 1, 1)
-- first row - so flag should be set
INSERT INTO TestTable VALUES ('QQQ', 'XASE', 2, 1)
-- second row - so flag should be set, but previous row should be unset
INSERT INTO TestTable VALUES ('MSFT', 'XASE', 2, 0)
-- second row - should be unset for this, previous row not changed

select * from TestTable ORDER BY Symbol, exch_no

UPDATE TestTable SET [PrimaryFlag] =0
WHERE [Symbol] = 'QQQ' AND [Exchange] = 'XNYS'
-- set flag, unset first row

select * from TestTable ORDER BY Symbol, exch_no

DELETE FROM TestTable WHERE [Symbol] = 'QQQ' AND [Exchange] = 'XASE'
-- first row should be set
DELETE FROM TestTable WHERE [Symbol] = 'MSFT' AND [Exchange] = 'XASE'
-- no change to flags
GO

SELECT * FROM [TestTable] ORDER BY Symbol, exch_no

--
Erland Sommarskog, SQL Server MVP, so****@algonet. se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #5
Jason (Ja*******@hotm ail.com) writes:
1) What is wrong with my names? They sound reasonable to me. No
abbreviations and the name tells you want the column represents.
There is nothing wrong with your names. Of course, "exchange" is a little
abstract for someone who don't know the business domain, but that is
not relevant.
3) I realize that there is no such thing as first or second row. I was
merely using those words in comments to signify a particular row being
inserted before the others. In other words, the MSFT/XNAS row was
inserted first, then the MSFT/ASE row was inserted.
Joe has a point so far that you need to somehow cover this in the data
model. Of course, "first" could also mean the alphabetic order of the
exchange code, or whatever.
4) Did not know about the BIT datatype. Good to know.
Unless you are striving for portability, there is no reason to stay away
from datatypes that are proprietary to SQL Server. Joe Celko seems to
think that everyone changes their DB engine at least twice a year.
5) When you say that flags are bad SQL programming, you are talking
about true/false or yes/no types of columns? Your comment says to
order them using integer values. In my case, each symbol only has ONE
primary exchange, the rest are not. There is no preference or order to
the none primary exchanges.
Good knows what Joe meant. Joe is good if you want to know some theory,
or help devlish SELECT statements. But for general programming help
for MS SQL Server his advice are not always appropriate.
6) Why code the one-and-only-one primary exchange logic in a stored
procedure as opposed to a trigger? By having it in a stored procedure
I am limited to single security inserts since cannot pass datasets as
parameters. I can also have the problem of having somebody NOT use the
SP and then I have multiple primary exchanges for a single security.


Actually, you can pass data sets to stored procedures these days, thanks
to the wonders of XML.

That said, your comment is very relevant. Whether to use a trigger or to
have the logic in a stored procedure is a question that is always open
for discussion. Having a trigger, means that if someone bypasses the
trigger by running an SQL statement direct, you maintain the logic.
However, a trigger can be dropped or disabled, and if this happens,
your updating logic will fail silently. A stored procedure can also
be dropped, but attempts to call it will give an error message.
--
Erland Sommarskog, SQL Server MVP, so****@algonet. se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techinf...2000/books.asp
Jul 20 '05 #6
Thanks for the help.

Going back and rereading my own post exposed some questionable
requirements.

If the security that is being updated currently has the primary
exchange flag set and you are currently trying to turn it off, who
then becomes the primary exchange?!

One possible answer would be SELECT TOP 1 but a better response would
be not to allow it to happen. The business rule should probably be
that a security cannot have its primary flag unset manually, but can
only be changed by setting another row as the primary.
Jul 20 '05 #7
>> 1) What is wrong with my names? They sound reasonable to me. No
abbreviations and the name tells you want the column represents. <<

ISO-11179 is more of a "genus-specie" model. If these are known in
your trade, then they can stand along
2) Yes there are variable length (and greater than) 5 character symbols) <<

That is one I did not know! I am still tryignto figure out CUSIP
rules. Thanks!
5) When you say that flags are bad SQL programming, you are talking about true/false or yes/no types of columns? <<

They are all too often a computed column. You would not store the
total cost of a line item in an invoice detail when you have price and
quantity in the same row. You would not store the total cost of an
invoice in an invoice header when you can computer them from the
invoice details. It is faster these days to compute them as needed
and it is safer (we used to have to do this with punch cards for
physical reasons). So why would you have the logical status in a
computed column either?
In my case, each symbol only has ONE primary exchange, the rest are not. There is no preference or order to the none primary exchanges. <<

Then consider just "prefer = 1 or prefer >1 " in your queries. The
sequence gives you a simple datatype with easy validation and update
rules. Bits don't.
6) Why code the one-and-only-one primary exchange logic in a stored procedure as opposed to a trigger? <<

Triggers are less portable in SQL Server. I also assume that you
would do other edits in the SP.
I can also have the problem of having somebody NOT use the SP and

then I have multiple primary exchanges for a single security. <<

Good point. If we get to full Standard SQL-92, you can do it with a
CHECK() constraint, which would be the best way.
Jul 20 '05 #8
>> I can also have the problem of having somebody NOT use the SP and
then I have multiple primary exchanges for a single security. <<

CREATE TABLE SecuritiesExcha nges
(symbol CHAR(5) NOT NULL,
exchange_code CHAR(5) NOT NULL
CHECK (exchange_code IN (…)),
exch_prefer INTEGER DEFAULT 1 NOT NULL
CHECK (exch_prefer >= 0),
PRIMARY KEY (exchange, symbol, exch_prefer),
UNIQUE (symbol, exch_prefer) -- does that do it?
);
Jul 20 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2207
by: m3ckon | last post by:
Hi there, I'm a little stuck and would like some help I need to create an update trigger which will run an update query on another table. However, What I need to do is update the other table with the changed record value from the table which has the trigger.
9
3471
by: Martin | last post by:
Hello, I'm new with triggers and I can not find any good example on how to do the following: I have two tables WO and PM with the following fields: WO.WONUM, VARCHAR(10) WO.PMNUM, VARCHAR(10) WO.PROBLEMCODE, VARCHAR(8)
3
7291
by: takilroy | last post by:
Hi, Does anyone know of a simple way to do this? I want to create an insert trigger for a table and if the record already exists based on some criteria, I want to update the table with the values that are passed in via the insert trigger without having to use all the 'set' statements for each field (so if we add fields in the future I won't have to update the trigger). In other words, I want the trigger code to look something like...
33
4795
by: coosa | last post by:
I have a table: ---------------------------------------------------- CREATE TABLE CATEGORY ( CATEGORY_ID INTEGER IDENTITY(1,1) NOT NULL, CATEGORY_NAME VARCHAR(40) NOT NULL, PARENT_CATEGORY_ID INTEGER, CATEGORY_ICON IMAGE, DEPTH INTEGER,
5
3971
by: Peter Erickson | last post by:
I am running postgresql 7.4.2 and having problems creating a trigger function properly. I keep getting the following error: ERROR: OLD used in query that is not in rule I have a table called journal_entries with a foreign key to a table called journals. When a entry is added to journal_entries, I am trying to get it to update the 'mtime' field of the corresponding entry in the journals table.
4
1976
by: SUKRU | last post by:
Hello everybody. Unfortunately I am pretty new to sql-server 2000 I need some help with a Trigger I created. I created a trigger witch takes the id of the affected row and does a update on a other table with that ID. The trigger works fine with one affected row. But when there are more then one rows affected, i get an error. I found out that SQL-server does not support row-level triggers. I should probable make my own cursor and...
3
3735
by: teddysnips | last post by:
I need a trigger (well, I don't *need* one, but it would be optimal!) but I can't get it to work because it references ntext fields. Is there any alternative? I could write it in laborious code in the application, but I'd rather not! DDL for table and trigger below. TIA
2
4984
by: mob1012 via DBMonster.com | last post by:
Hi All, I wrote last week about a trigger problem I was having. I want a trigger to produce a unique id to be used as a primary key for my table. I used the advice I received, but the trigger is still not working correctly. Here is my code: create trigger emp_update_id BEFORE update on emp_update REFERENCING NEW AS N for each row SET unique_id = Generate_unique();
3
1941
by: Sam Durai | last post by:
Need help to write a trigger according to the following business requirement. This on DB2 UDB V8.2 / AIX 5.3 Whenever a 100th record is inserted into my 'ACCOUNT' table with a particular 'BATCH_ID' I need to either update or insert a row onto 'DESCRIPTION column of STATUS' table as verified for that particular BATCH_ID. Any help is greatly appreciated.
0
9944
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9797
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11154
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10762
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10863
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9586
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6005
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4622
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3241
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.