Monday, July 11, 2005

Specifying INSERT Columns

Here is a quick one that I touched on briefly in one of my first blogs:

http://thinkoracle.blogspot.com/2005/05/null-vs-nothing.html

It can be important to specify which columns you plan on providing values for in an INSERT statement. Repeating Dan Morgan's quote:

"By not specifying column names you are signifying that you are providing values for ALL columns. This is why it is a very bad practice as doing an ALTER TABLE ADD immediately invalidates all SQL statements."

Here is an example. I created a table, and then wrote a procedure that will insert a row WITHOUT specifying the values. Works fine if the table doesn't change:

SET SERVEROUTPUT ON;

CREATE TABLE MyTable (MyInt NUMBER);

CREATE OR REPLACE PROCEDURE InsertIntoMyTable (InValue IN NUMBER)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Inserting ' || InValue || ' into MyTable');
INSERT INTO MyTable VALUES (InValue);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);

END InsertIntoMyTable;
/

EXEC InsertIntoMyTable(1);
Inserting 1 into MyTable

PL/SQL procedure successfully completed.

So let's try modifying the table, and try again.

ALTER TABLE MyTable ADD (MyString VARCHAR2(32));

EXEC InsertIntoMyTable(2);
BEGIN InsertIntoMyTable(2); END;

*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object SCOTT.INSERTINTOMYTABLE is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

The procedure fails, and can't recompile. Perhaps you want that behaviour, because you want to require all your procedures to be checked every time a related table has changed. But, then again, maybe you don't.

In that case, modify the stored procedure to specify which value you are inserting, and then you're good to go. Let's repeat this test that way:

CREATE OR REPLACE PROCEDURE InsertIntoMyTable (InValue IN NUMBER)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('Inserting ' || InValue || ' into MyTable');
INSERT INTO MyTable (MyInt) VALUES (InValue);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);

END InsertIntoMyTable;
/

SQL> EXEC InsertIntoMyTable(2);
Inserting 2 into MyTable

PL/SQL procedure successfully completed.

SQL> ALTER TABLE MyTable ADD (MyOtherInt NUMBER);

Table altered.

SQL> EXEC InsertIntoMyTable(3);
Inserting 3 into MyTable

PL/SQL procedure successfully completed.

Comments:
not satisfied
 
This comment has been removed by a blog administrator.
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?