== Why is this an issue?

Since databases don't offer "Are you sure?" dialogs, it's best to be very certain of what you're changing before you do it. ``++UPDATE++`` and ``++DELETE++`` statements that don't precisely limit their effects to single rows risk changing more than was intended. That's why they should be reviewed carefully.


This rule raises an issue when an ``++UPDATE++`` or ``++DELETE++`` statement's ``++WHERE++`` clause does not use precisely either a unique index or all parts of the table's primary key. That includes both cases where they are omitted in whole or in part, and when they are used but could still describe multiple rows. E.G. ``++WHERE AGE = 34++``, and ``++WHERE TABLE_ID > 0 AND TABLE_ID < 40++``.


*Note* That this rule raises issues only when a database catalog is provided during the SonarQube analysis.


=== Noncompliant code example

[source,cobol]
----
CREATE table my_table (
     compound_a integer not null,
     compound_b integer not null,
     column_c varchar(50),
     primary key (compound_a, compound_b)
);

DELETE FROM my_table
WHERE compound_b=4;  -- Noncompliant
----


=== Exceptions

Statements using a cursor and ``++WHERE CURRENT OF++`` are ignored.


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Review carefully this "UPDATE|DELETE" statement which might impact multiple rows.


=== Highlighting

entire WHERE clause


'''
== Comments And Links
(visible only on this page)

=== on 8 Jan 2016, 17:21:50 Pierre-Yves Nicolas wrote:
I don't think that the rule title is very clear. What about "UPDATE and DELETE statements should not impact more than one row"?


This rule should not only check primary keys: a unique index may also guarantee that a statement will not update more than 1 row.


It seems that we have to exclude statements using "WHERE CURRENT OF" (with a cursor).


This rule may overlap RSPEC-1590 and RSPEC-3483: we can reduce the scope of RSPEC-3483 to SELECT statements.



=== on 11 Jan 2016, 18:31:47 Ann Campbell wrote:
I've made the changes you suggested [~pierre-yves.nicolas], and am assigning this back to @Freddy for his initial review.

=== on 19 Jan 2016, 10:14:26 Pierre-Yves Nicolas wrote:
What should be the behavior of this rule if a table has no primary key and no unique index?

Of course, in such a case, every UPDATE or DELETE can then impact multiple rows.

On the other hand, we could consider that the problem is on the database structure side, not in the COBOL code using the table.

=== on 19 Jan 2016, 10:44:58 Pierre-Yves Nicolas wrote:
I think that we should change the message for that rule:

* This rule is not only about primary keys, but also about unique indexes. 
* Primary keys or unique indexes are not always "compound", they may have a single column.

Suggested message: "Change this UPDATE|DELETE statement so that it does not update|delete more than one row"

=== on 19 Jan 2016, 10:51:31 Ann Campbell wrote:
Done [~pierre-yves.nicolas]

=== on 19 Jan 2016, 10:54:48 Ann Campbell wrote:
\[~pierre-yves.nicolas] without a PK and/or unique index, we have no way of knowing how many rows a statement will affect. Perhaps we need to add a rule saying that each table should have a primary key?

=== on 19 Jan 2016, 11:07:18 Pierre-Yves Nicolas wrote:
\[~ann.campbell.2] We may add a rule requiring a primary key, but I think it should be implemented only in plugins working purely on the database side, e.g. PLSQL plugin.

=== on 19 Jan 2016, 12:04:41 Ann Campbell wrote:
Of course [~pierre-yves.nicolas]

endif::env-github,rspecator-view[]
