The relational database is an extremely powerful abstraction; it's a collection of facts and a predicate calculus. Not only that, SQL enforces command query separation by having one clause for examining rows and another for changing rows.
When you think of a database as a truth reasoning engine, it makes sense to have a set-up that does not allow contradictions to flow from the data you're modelling. Therefore, to use a relational database effectively you need to get your database design right. Unlike the design of object orientated programs, there is a consensus view on how a relational database should be designed. The proper approach to database design is normalise as far as it is sensible. Most people normalise up to third normal form but you can in fact go up to fifth normal form.
If possible, you want to expunge null column values from your database. If you agree with my view of the database as a truth reasoning engine, then nulls are a real problem. When you have nulls in a database the law of excluded middle does not hold. This makes "proof by contradiction" of any given property of the database more difficult that it would be without the nulls. Nulls unnecessarily complicate the semantics of the database.
Sometimes it will be necessary to break the rules of normalisation for performance reasons. However, don't do this before you have data on what is queries in particular are slow. Often you can simply speed up the query by carefully altering indexes rather than denormalising.
Finally, a word on stored procedures rather than direct queries. On a decent database, you can set security permissions on stored procedures independently of the underlying tables. This, by itself, is reason enough to consider using stored procedures extensively. With stored procedures, you build a tighter security model than is possible with direct SQL access.