Tải bản đầy đủ (.pdf) (5 trang)

SQL PROGRAMMING STYLE- P21 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (89.96 KB, 5 trang )

6.2 Pick Compact Constructions over Longer Equivalents 117
which is a little cleaner than:
WHERE (a IN (x, y) OR z IS NULL)
6.2.4.3 Use CASE Expressions, Not Complex Nested Predicates
An advanced trick in the WHERE clause is to use a CASE expression for
a complex predicate with material implications. If you forgot your
freshman logic, a material implication logical operator is written as an
arrow with two tails, and it means “p implies q” or “if p is true then q is
true” in English.
WHERE CASE
WHEN <search condition #1>
THEN 1
WHEN <search condition #2>
THEN 1

ELSE 0 END = 1
The use of a function that returns one or zero when given a predicate
as its parameter is called a characteristic function in logic and set theory.
Review the rules for the CASE expression in section 6.2.2 first, so you
understand it. The order of execution of the WHEN clauses can be used
to optimize performance and avoid redundant tests. You can also nest
CASE expressions inside the WHEN and THEN clauses of a containing
CASE expression and display the logic as an indented tree structure.
WHERE CASE
WHEN <search condition #1>
THEN CASE
WHEN <search condition #1.1>
THEN 1
WHEN <search condition #1.2>
THEN 1 ELSE 0 END
WHEN <search condition #2>


THEN 1

ELSE 0 END = 1
The goal of this technique is to replace pages of long lists of simple
theta expressions inside horrible levels of parentheses and to provide
118 CHAPTER 6: CODING CHOICES
some short-circuit evaluation as a bonus. When the nesting is too messy
to understand, stop and reconsider your logic. Decision table tools, such
as Logic Gem, are an excellent way to do this.
6.3 Use Comments
Rationale:
The best documentation for maintaining a program has been comments
in the code. Perhaps it is easier for procedural language programmers to
add comments because they are explaining in a narrative fashion what
their program is doing. Unfortunately, procedural language comments
are often redundant if you can read the code. How much help did you
get from:
UPDATE Teams
SET score = score + 1;—increment score
which gives you no information about what the variable score means and
why it is incremented.
In Standard SQL, a comment begins with two dashes ( ) and ends
with a new line, because the first SQL engines were on IBM mainframes
and used punchcards. This format is a poor choice with modern
computers that can store free-form text. Word wrap in program text can
split a comment and give you errors. Because SQL supports the unary
minus operator, this is ambiguous in some rare situations and makes the
compiler work extra hard. Later standards added the C style /* and */
pairs, and many vendors have similar comment brackets. They are a
better choice.

SQL programmers do not like to put comments in their code, not
even redundant or useless ones. My guess is that because SQL does a lot
of work in one statement and programmers have been taught to
comment the code at the statement execution level rather than explain
the purpose of the code, the higher level of abstraction confuses them.
They are not inclined to put comments at the clause level because the
appearance of the code can be crowded.
Get over it. You need a high-level descriptive comment on a block of
SQL, and then more detailed comments on a few important clauses. Try
to keep the comments aimed at non-SQL programmers and in plain
English. For example, don’t say “relational division of motor pool
vehicles by available drivers” on the assumption that the reader will
6.3 Use Comments 119
know what a relational division is. Try “list all drivers who can drive all
the vehicles in the motor pool” instead. The other trick is to reference the
documentation for the schema and the applications. This assumes that
they are current and useful, however.
If you have the time, another guru-level trick is to save the best of the
various statements you tried that worked but did not perform as well as
the final choice as comments. In SQL, what was the best answer in one
situation is often no longer the best answer. Instead of making the next
programmer start from scratch, share your notes.
Exceptions:
In a well-designed schema with good data element names, much of the
code is easy for an experienced SQL programmer to read. You can skip
comments on single statements if their intent is really obvious, but
remember that one programmer’s obvious is another’s “what the heck?”
when you code.
6.3.1 Stored Procedures
Always start a stored procedure with a comment that gives at least the

author, the date, and the update history. This is simply basic software
management. After that, add a high-level description of the function of
this module. The procedure name will be in a “<verb><object>” format.
Each parameter should have a comment as needed.
6.3.2 Control Statement Comments
Comments on control statements, such as IF-THEN-ELSE, BEGIN-END,
and WHILE-DO loops, will look much like comments in any procedural
program. Complicated SQL statements need a comment at the top and
often comments at the clause level.
6.3.3 Comments on Clause
This point is difficult to generalize, but things that act as a unit might
need a comment. For example, a derived table for which there is no good
alias might need a comment to explain what it contains. A series of
predicates that define a complicated join might be prefaced with a
comment to explain what they are doing at a higher level.
120 CHAPTER 6: CODING CHOICES
6.4 Avoid Optimizer Hints
Rationale:
Many products have proprietary syntax for sending parameters to the
optimizer to change the execution plan for a statement. Because each
physical implementation is different, this syntax will not be portable, but
there are other problems too.
First, the optimizer is usually smarter than the programmer and finds
a good plan. People cannot handle computations that involve tens of
parameters very well. Second, once a hint is put on a statement, it stays
there permanently, long after the reason for the hint is gone. A typical
example of this would set up a query hint for a skewed statistical
distribution and then, as the database grows, the distribution becomes
more normal or skewed in the opposite direction. The hint that used to
be so helpful is now a handicap.

Exceptions:
If you do have a skewed statistical distribution or other weirdness in your
data that is destroying performance, then use a hint. Set up a review of
all statements with hints to see if they actually need to be maintained.
Reviews should occur when a new release of database is installed
(optimizer might be better) or the statistics of one or more of the tables
change (data might be better), but if the performance is acceptable, then
do not use hints.
6.5 Avoid Triggers in Favor of DRI Actions
Rationale:
Although there is an ANSI/ISO standard for triggers, their syntax and
semantics are still highly proprietary. Triggers are blocks of procedural
code that are executed (fired) when a database event occurs to a table.
This code is usually in a proprietary 3GL language. A database event is
something that changes the data—an insert, update, or delete.
The full ANSI version of triggers does not fire on an insertion, but
some vendor products do. The full ANSI version of triggers have more
than one trigger on a table and can fire them in a sequence either before
or after the database event. Most vendor products do not have that much
control over the triggers. On the other hand, the syntax and semantics
for DRI actions are well defined and standardized.
A newbie posted a topic under the title “Need Help with a Calculation
Trigger” on the forums in the SQL Server Central Web site in November
2004. This person was having trouble setting up a trigger to check the
6.5 Avoid Triggers in Favor of DRI Actions 121
units of a “number field [sic]”; the real problem was that the poster did
not know that a column is not a field.
For some reason, the column was declared as FLOAT and was called
length. The trouble is that some people were entering a length in meters,
centimeters, and millimeters. The poster was trying to code a trigger that

will fire on UPDATE or INSERT to check the value of length. If it is
greater than 20, chances are the number is in millimeters and should be
divided by 10. If the number is less than 0, then the number is probably
in meters and should be multiplied by 100.
CREATE TRIGGER SetCentimeters
AFTER INSERT ON Samples
UPDATE Samples
SET length
= (CASE
WHEN length > 10.00
THEN Length / 10.00
WHEN length < 0.00
THEN Length * 100.00
ELSE Length END)
WHERE length NOT BETWEEN 0.00 AND 10.00;
However, this is the wrong answer. It is in procedural code. The right
answer is in the DDL, with something like this:
length DECIMAL(2,1) NOT NULL
CONSTRAINT length_in_centimeters_only
CHECK (length BETWEEN 0.01 AND 9.99)
Triggers tend to fix errors on the fly; the goal is not to permit them in
the first place.
Exceptions:
Some things should be done with triggers because you cannot do them
with DRI. In particular, the INSTEAD OF trigger has to be used for
updatable views. This trigger is attached to a VIEW, and instead of taking
actions on the VIEW, it changes the base tables from which the VIEW is
built, so that the user sees those changes reflected in the VIEW.
Heuristics tend to favor stored procedures over triggers. A trigger
fires every time its database event occurs, which puts it out of your

control and adds that overhead to each database event. A stored

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×