Geeks With Blogs

News


Rodney Vinyard - .NET & SQL Developer When all is said and done, more will be said than done

User-Defined Functions

Scalar User-Defined Function

A Scalar user-defined function returns one of the scalar data types. Text, ntext, image and timestamp data types are not supported. These are the type of user-defined functions that most developers are used to in other programming languages.

Table-Value User-Defined Function

An Inline Table-Value user-defined function returns a table data type and is an exceptional alternative to a view as the user-defined function can pass parameters into a T-SQL select command and in essence provide us with a parameterized, non-updateable view of the underlying tables.

Multi-statement Table-Value User-Defined Function

A Multi-Statement Table-Value user-defined function returns a table and is also an exceptional alternative to a view as the function can support multiple T-SQL statements to build the final result where the view is limited to a single SELECT statement. Also, the ability to pass parameters into a T-SQL select command or a group of them gives us the capability to in essence create a parameterized, non-updateable view of the data in the underlying tables. Within the create function command you must define the table structure that is being returned. After creating this type of user-defined function, I can use it in the FROM clause of a T-SQL command unlike the behavior found when using a stored procedure which can also return record sets.

CREATE FUNCTION dbo.customersbycountry ( @Country varchar(15) )

RETURNS

        @CustomersbyCountryTab table (

               [CustomerID] [nchar] (5), [CompanyName] [nvarchar] (40),

               [ContactName] [nvarchar] (30), [ContactTitle] [nvarchar] (30),

               [Address] [nvarchar] (60), [City] [nvarchar] (15),

               [PostalCode] [nvarchar] (10), [Country] [nvarchar] (15),

               [Phone] [nvarchar] (24), [Fax] [nvarchar] (24)

        )

AS

BEGIN

        INSERT INTO @CustomersByCountryTab

        SELECT [CustomerID],

                       [CompanyName],

                       [ContactName],

                       [ContactTitle],

                       [Address],

                       [City],

                       [PostalCode],

                       [Country],

                       [Phone],

                       [Fax]

        FROM [Northwind].[dbo].[Customers]

        WHERE country = @Country

       

        DECLARE @cnt INT

        SELECT @cnt = COUNT(*) FROM @customersbyCountryTab

       

        IF @cnt = 0

               INSERT INTO @CustomersByCountryTab (

                       [CustomerID],

                       [CompanyName],

                       [ContactName],

                       [ContactTitle],

                       [Address],

                       [City],

                       [PostalCode],

                       [Country],

                       [Phone],

                       [Fax]  )

               VALUES ('','No Companies Found','','','','','','','','')

       

        RETURN

END

GO

SELECT * FROM dbo.customersbycountry('USA')

SELECT * FROM dbo.customersbycountry('CANADA')

SELECT * FROM dbo.customersbycountry('ADF')

User Defined Functions (UDF) Limitations

UDF have its own advantage and usage but in this article we will see the limitation of UDF. Things UDF can not do and why Stored Procedure are considered as more flexible then UDFs. Stored Procedure are more flexibility then User Defined Functions(UDF).

  • UDF has No Access to Structural and Permanent Tables.
    • UDF can call Extended Stored Procedure, which can have access to structural and permanent tables. (No Access to Stored Procedure)
  • UDF Accepts Lesser Numbers of Input Parameters.
    • UDF can have upto 1023 input parameters, Stored Procedure can have upto 21000 input parameters.
  • UDF Prohibit Usage of Non-Deterministic Built-in Functions
    • Functions GETDATE() etc can not be used UDFs, but can be used in Stored Procedure
  • UDF Returns Only One Result Set or Output Parameter
    • Due to this it can be used in SELECT statement but can not return multiple result set like Stored Procedure
  • UDF can not Call Stored Procedure
    • Only access to Extended Stored Procedure.
  • UDF can not Execute Dynamic SQL or Temporary Tables
    • UDF can not run dynamic SQL which are dynamically build in UDF. Temporary Tables can not be used in UDF as well.
  • UDF can not Return XML
    • FOR XML is not allowed in UDF
  • UDF does not support SET options
    • SET options which can change Server level or transaction level settings are prohibited in UDFs. (SET ROWCOUNT etc)
  • UDF does not Support Error Handling
    • RAISEERROR or @@ERROR are not allowed in UDFs.

 

CREATE FUNCTION whichContinent

Isolation Levels

SET TRANSACTION ISOLATION LEVEL

    { READ UNCOMMITTED

    | READ COMMITTED

    | REPEATABLE READ

    | SNAPSHOT

    | SERIALIZABLE

    }

[ ; ]

 

READ UNCOMMITTED

Specifies that statements can read rows that have been modified by other transactions but not yet committed.

Nonrepeatabel read: If somebody performed UPDATE or DELETE of any of the rows you read earlier.

Phantom: If anybody INSERTed a row within the range you had for an earlier query (i.e., you see new rows).

READ COMMITTED

Specifies that statements can only read data that has been committed by other transactions. This prevents dirty reads. Data can be changed by other transactions between individual statements within the current transaction, resulting in nonrepeatable reads or phantom data. This option is the SQL Server default.

REPEATABLE READ

Specifies that statements cannot read data that has been modified but not yet committed by other transactions and that no other transactions can modify data that has been read by the current transaction until the current transaction completes.

SNAPSHOT

Specifies that data read by any statement in a transaction will be the transactionally consistent version of the data that existed at the start of the transaction. The transaction can only recognize data modifications that were committed before the start of the transaction. Data modifications made by other transactions after the start of the current transaction are not visible to statements executing in the current transaction. The effect is as if the statements in a transaction get a snapshot of the committed data as it existed at the start of the transaction.

SERIALIZABLE

Specifies the following:

·         Statements cannot read data that has been modified but not yet committed by other transactions.

·         No other transactions can modify data that has been read by the current transaction until the current transaction completes.

·         Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.

Lock types

There are three main types of locks that SQL Server 7.0/2000 uses:

·  Shared locks

·  Update locks

·  Exclusive locks

Shared locks are used for operations
that do not change or update data, such as a SELECT statement.

Update locks are used when SQL Server intends to modify a page, and later promotes the update page lock to an exclusive page lock before actually making the changes.

Exclusive locks are used for the data modification operations, such as UPDATE, INSERT, or DELETE.

Shared locks are compatible with other Shared locks or Update locks.

Update locks are compatible with Shared locks only.

Exclusive locks are not compatible with other lock types.

 

Deadlocks

ways to avoid cursors include:

  • Rewriting the cursor as a normal query. Some people write cursors that perform the same task over and over on a set of records. This is a waste of server resources because this could be easily handled by a standard query. And even if what you need to do to each row is conditional on data in a row, you still may be able to to use a standard query using a CASE statement.
  • Rewriting the cursor as a derived query. See this article for more information.
  • Rewriting the cursor using temporary tables in a query. See this article for more information.
  • Rewriting the cursor using table variables in a query (SQL Server 2000 or 2005).

joins options in SQL Server:

  • INNER JOIN - Match rows between the two tables specified in the INNER JOIN statement based on one or more columns having matching data.  Preferably the join is based on referential integrity enforcing the relationship between the tables to ensure data integrity.
    • Just to add a little commentary to the basic definitions above, in general the INNER JOIN option is considered to be the most common join needed in applications and/or queries.  Although that is the case in some environments, it is really dependent on the database design, referential integrity and data needed for the application.  As such, please take the time to understand the data being requested then select the proper join option.
    • Although most join logic is based on matching values between the two columns specified, it is possible to also include logic using greater than, less than, not equals, etc.
  • LEFT OUTER JOIN - Based on the two tables specified in the join clause, all data is returned from the left table.  On the right table, the matching data is returned in addition to NULL values where a record exists in the left table, but not in the right table.
    • Another item to keep in mind is that the LEFT and RIGHT OUTER JOIN logic is opposite of one another.  So you can change either the order of the tables in the specific join statement or change the JOIN from left to right or vice versa and get the same results.
  • RIGHT OUTER JOIN - Based on the two tables specified in the join clause, all data is returned from the right table.  On the left table, the matching data is returned in addition to NULL values where a record exists in the right table but not in the left table.
  • Self -Join - In this circumstance, the same table is specified twice with two different aliases in order to match the data within the same table.
  • CROSS JOIN - Based on the two tables specified in the join clause, a Cartesian product is created if a WHERE clause does filter the rows.  The size of the Cartesian product is based on multiplying the number of rows from the left table by the number of rows in the right table.  Please heed caution when using a CROSS JOIN.
  • FULL JOIN - Based on the two tables specified in the join clause, all data is returned from both tables regardless of matching data.

Stored Proc Error Handling

 

Fatal Error

 

SELECT * FROM NonExistentTable

 

 

Non Fatal

INSERT a row into table and omit a column

 

RAISERROR ( { msg_id | msg_str | @local_variable }

    { ,severity ,state }

    [ ,argument [ ,...n ] ] )

    [ WITH option [ ,...n ] ]

 

Uncommittable Transactions and XACT_STATE

If an error generated in a TRY block causes the state of the current transaction to be invalidated, the transaction is classified as an uncommittable transaction. An error that ordinarily ends a transaction outside a TRY block causes a transaction to enter an uncommittable state when the error occurs inside a TRY block. An uncommittable transaction can only perform read operations or a ROLLBACK TRANSACTION. The transaction cannot execute any Transact-SQL statements that would generate a write operation or a COMMIT TRANSACTION. The XACT_STATE function returns a value of -1 if a transaction has been classified as an uncommittable transaction. When a batch finishes, the Database Engine rolls back any active uncommittable transactions. If no error message was sent when the transaction entered an uncommittable state, when the batch finishes, an error message will be sent to the client application. This indicates that an uncommittable transaction was detected and rolled back.

Using TRY…CATCH with XACT_STATE

The following example shows how to use the TRY…CATCH construct to handle errors that occur inside a transaction. The XACT_STATE function determines whether the transaction should be committed or rolled back. In this example, SET XACT_ABORT is ON. This makes the transaction uncommittable when the constraint violation error occurs.

Copy

USE AdventureWorks2008R2;

GO

 

-- Check to see whether this stored procedure exists.

IF OBJECT_ID (N'usp_GetErrorInfo', N'P') IS NOT NULL

    DROP PROCEDURE usp_GetErrorInfo;

GO

 

-- Create procedure to retrieve error information.

CREATE PROCEDURE usp_GetErrorInfo

AS

    SELECT

        ERROR_NUMBER() AS ErrorNumber

        ,ERROR_SEVERITY() AS ErrorSeverity

        ,ERROR_STATE() AS ErrorState

        ,ERROR_LINE () AS ErrorLine

        ,ERROR_PROCEDURE() AS ErrorProcedure

        ,ERROR_MESSAGE() AS ErrorMessage;

GO

 

-- SET XACT_ABORT ON will cause the transaction to be uncommittable

-- when the constraint violation occurs.

SET XACT_ABORT ON;

 

BEGIN TRY

    BEGIN TRANSACTION;

        -- A FOREIGN KEY constraint exists on this table. This

        -- statement will generate a constraint violation error.

        DELETE FROM Production.Product

            WHERE ProductID = 980;

 

    -- If the DELETE statement succeeds, commit the transaction.

    COMMIT TRANSACTION;

END TRY

BEGIN CATCH

    -- Execute error retrieval routine.

    EXECUTE usp_GetErrorInfo;

 

    -- Test XACT_STATE:

        -- If 1, the transaction is committable.

        -- If -1, the transaction is uncommittable and should

        --     be rolled back.

        -- XACT_STATE = 0 means that there is no transaction and

        --     a commit or rollback operation would generate an error.

 

    -- Test whether the transaction is uncommittable.

    IF (XACT_STATE()) = -1

    BEGIN

        PRINT

            N'The transaction is in an uncommittable state.' +

            'Rolling back transaction.'

        ROLLBACK TRANSACTION;

    END;

 

    -- Test whether the transaction is committable.

    IF (XACT_STATE()) = 1

    BEGIN

        PRINT

            N'The transaction is committable.' +

            'Committing transaction.'

        COMMIT TRANSACTION;  

    END;

END CATCH;

GO

 

Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance

 

http://www.sql-server-performance.com/articles/per/temp_tables_vs_variables_p1.aspx

There are three major theoretical differences between temporary tables:

create table #T (…)

And table variables:

declare @T table (…)

1.      transaction logs are not recorded for the table variables. Hence, they are out of scope of the transaction mechanism, i.e. table variable updates within a transaction cannot be rolled back

a.       table variables no transactions

2.      temporary table cannot be pre-compiled, while an execution plan of procedures with table variables can be statically compiled in advance. Pre-compiling a script gives a major advantage to its speed of execution. This advantage can be dramatic for long procedures, where recompilation can be too pricy

a.       table variables can be pre-compiled execution plan

3.      table variables exist only in the same scope as variables. Contrary to the temporary tables, they are not visible in inner stored procedures and in exec(string) statements. Also, they cannot be used in an insert/exec statement.

a.       table variables limited scope

PIVOT and UNPIVOT Table Examples

 

http://blog.sqlauthority.com/2008/06/07/sql-server-pivot-and-unpivot-table-examples/

 

n        Creating Test Table
CREATE TABLE Product(Cust VARCHAR(25), Product VARCHAR(20), QTY INT)
GO
-- Inserting Data into Table
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',2)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','SODA',6)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','MILK',1)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','BEER',12)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','MILK',3)
INSERT INTO Product(Cust, Product, QTY)
VALUES('FRED','BEER',24)
INSERT INTO Product(Cust, Product, QTY)
VALUES('KATE','VEG',3)
GO

 

Pivot Table ordered by CUST
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT
(SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt
ORDER BY CUST
GO
-- Unpivot Table ordered by CUST
SELECT CUST, PRODUCT, QTY
FROM
(
SELECT CUST, VEG, SODA, MILK, BEER, CHIPS
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT
( SUM(QTY) FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)) AS pvt) p
UNPIVOT
(QTY FOR PRODUCT IN (VEG, SODA, MILK, BEER, CHIPS)
)
AS Unpvt
GO

 

Tips on Optimizing Covering Indexes

By : Brad McGehee
Jan 19, 2007

 

 

If you have to use a non-clustered index (because your single clustered index can be used better elsewhere in a table), and if you know that your application will be performing the same query over and over on the same table, consider creating a covering index on the table for the query. A covering index, which is a form of a composite index, includes all of the columns referenced in the SELECT, JOIN, and WHERE clauses of a query. Because of this, the index contains the data you are looking for and SQL Server doesn't have to look up the actual data in the table, reducing logical and/or physical I/O, and boosting performance.

On the other hand, if the covering index gets too big (has too many columns), this could actually increase I/O and degrade performance. Generally, when creating covering indexes, follow these guidelines:

  • If the query or queries you run using the covering index are seldom run, then the overhead of the covering index may outweigh the benefits it provides.
  • The covering index should not add significantly to the size of the key. If it does, then it its use may outweigh the benefits it provides.
  • The covering index must include all columns found in the SELECT list, the JOIN clause, and the WHERE clause.

SQL Server performance tips

 

User Defined Functions (UDF)

Refrain from using user defined functions (UDF) in a select statement that may potentially return many records. UDFs are executed as many times as there are rows in a returned result. A query that returns 100,000 rows calls the UDF 100,000 times.

SQL Server table indexes

Create SQL statements that utilize defined table indexes. Using indexes minimizes the amount of table scan which in most cases will be much slower than an index scan.

Multiple disks

The single best performance increase on a SQL Server computer comes from spreading I/O among multiple drives. Adding memory is a close second. Having many smaller drives is better than having one large drive for SQL Server machines. Even though the seek time is faster in larger drives, you will still get a tremendous performance improvement by spreading files, tables, and logs among more than one drive.

Disk controllers

Different disk controllers and drivers use different amounts of CPU time to perform disk I/O. Efficient controllers and drivers use less time, leaving more processing time available for user applications and increasing overall throughput.

SQL Server foreign keys

Ensure that all your tables are linked with foreign keys. foreign keys enhance the performance of queries with joins. Database tables inside each application are naturally related. Islands of tables are rarely needed if your application's business logic is well defined.

SQL Server primary keys

Ensure that every table has a primary key. if you can't find a natural set of columns to serve as a primary key, create a new column and make it a primary key on the table.

WHERE clause

In a WHERE clause, the various operators used can affect how fast a query is run. This is because some operators lend themselves to speed over other operators. Of course, you may not have any choice of which operator you use in your WHERE clauses, but sometimes you do.

Here are the key operators used in the WHERE clause, ordered by their performance. Those operators at the top will produce results faster than those listed at the bottom.

=

>, >=, <, <=

LIKE

<>

This lesson here is to use = as much as possible, and <> as least as possible. [2000, 2005, 2008] Updated 2-4-2009

*****

In a WHERE clause, the various operands used directly affect how fast a query is run. This is because some operands lend themselves to speed over other operands. Of course, you may not have any choice of which operand you use in your WHERE clauses, but sometimes you do.

Here are the key operands used in the WHERE clause, ordered by their performance. Those operands at the top will produce results faster than those listed at the bottom.

  • A single literal used by itself on one side of an operator.
  • A single column name used by itself on one side of an operator, a single parameter used by itself on one side of an operator.
  • A multi-operand expression on one side of an operator.
  • A single exact number on one side of an operator.
  • Other numeric number (other than exact), date, and time.
  • Character data, NULLs.

The simpler the operand, and using exact numbers, provides the best overall performance. [2000, 2005, 2008] Updated 2-4-2009

*****

If a WHERE clause includes multiple expressions, there is generally no performance benefit gained by ordering the various expressions in a particular order. This is because the SQL Server Query Optimizer automatically orders them (behind the scenes) for optimal performance. There are a few exceptions to this, which are discussed on this web site. [2000, 2005, 2008] Updated 2-4-2009

*****

By default, some developers, especially those who have not worked with SQL Server before, routinely include code similar to this in their WHERE clauses when they make string comparisons:

SELECT column_name FROM table_name

WHERE LOWER(column_name) = 'name'

In other words, these developers are making the assuming that the data in SQL Server is case-sensitive, which it generally is not. If your SQL Server database is not configured to be case sensitive, you don't need to use LOWER or UPPER to force the case of text to be equal for a comparison to be performed. Just leave these functions out of your code. This will speed up the performance of your query, as any use of text functions in a WHERE clause hurts performance.

But what if your database has been configured to be case-sensitive? Should you then use the LOWER and UPPER functions to ensure that comparisons are properly compared? No. The above example is still poor coding. If you have to deal with ensuring case is consistent for proper comparisons, use the technique described below, along with appropriate indexes on the column in question:

SELECT column_name FROM table_name

WHERE column_name = 'NAME' or column_name = 'name'

This code will run much faster than the first example. [2000, 2005, 2008] Updated 2-4-2009

*****

Try to avoid WHERE clauses that are non-sargable. The term "sargable" (which is in effect a made-up word) comes from the pseudo-acronym "SARG", which stands for "Search ARGument," which refers to a WHERE clause that compares a column to a constant value. If a WHERE clause is sargable, this means that it can take advantage of a useful index (assuming one is available) to speed completion of the query. If a WHERE clause is non-sargable, this means that the WHERE clause (or at least part of it) cannot take advantage of an index, instead performing a table/index scan, which may cause the query's performance to suffer.

Non-sargable search arguments in the WHERE clause, such as "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE '%500'" generally prevents (but not always) the query optimizer from using a useful index to perform a search. In addition, expressions that include a function on a column, expressions that have the same column on both sides of the operator, or comparisons against a column (not a constant), are not sargable.

But not every WHERE clause that has a non-sargable expression in it is doomed to a table/index scan. If the WHERE clause includes both sargable and non-sargable clauses, then at least the sargable clauses can use a useful index (if one exists) to help access the data quickly.

In many cases, if there is a covering index on the table, which includes all of the columns in the SELECT, JOIN, and WHERE clauses in a query, then the covering index can be used instead of a table/index scan to return a query's data, even if it has a non-sargable WHERE clause. But keep in mind that covering indexes have their own drawbacks, such as potentially producing very wide indexes that increase disk I/O when they are read.

In some cases, it may be possible to rewrite a non-sargable WHERE clause into one that is sargable. For example, the clause:

WHERE SUBSTRING(firstname,1,1) = 'm'

Can be rewritten like this:

WHERE firstname like 'm%'

Both of these WHERE clauses produce the same result, but the first one is non-sargable (it uses a function) and will run slower, while the second one is sargable, and will run much faster.

WHERE clauses that perform some function on a column are non-sargable. On the other hand, if you can rewrite the WHERE clause so that the column and function are separate, then the query can use an available useful index, greatly boosting performance. For example:

Function Acts Directly on Column, and Index Cannot Be Used:

SELECT member_number, first_name, last_name

FROM members

WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21

Function Has Been Separated From Column, and an Index Can Be Used:

SELECT member_number, first_name, last_name

FROM members

WHERE dateofbirth < DATEADD(yy,-21,GETDATE())

Each of the above queries produces the same results, but the second query will use an available, useful index because the function is not performed directly on the column, as it is in the first example. The moral of this story is to try to rewrite WHERE clauses that have functions so that the function does not act directly on the column.

WHERE clauses that use NOT are not sargable, but can often be rewritten to remove the NOT from the WHERE clause, for example:

WHERE NOT column_name > 5

To:

WHERE column_name <= 5

Each of the above clauses produces the same results, but the second one is sargable.

If you don't know if a particular WHERE clause is sargable or non-sargable, check out the query's execution plan in Query Analyzer or Management Studio. Doing this, you can very quickly see if the query uses available indexes as you expect.

 

Posted on Saturday, February 26, 2011 2:43 PM SQL Server 2005 Tricks , SQL Server 2000 Tricks | Back to top


Comments on this post: SQL Server Interview Questions

# re: SQL Server Interview Questions
Requesting Gravatar...
Thanks for this info! I was looking for this and I am greatly pleased to find it here.
Left by mobile phone tracking on May 14, 2011 4:16 AM

Your comment:
 (will show your gravatar)


Copyright © Rodney Vinyard | Powered by: GeeksWithBlogs.net