Thursday, July 29, 2010

LINQ {"Specified cast is not valid."} The value for column in table is DBNull.

Issue: While Querying the Dataset using LINQ Query, you get an error "{"Specified cast is not valid."} The value for column in table is DBNull."

Resolution: It it just the way you've written the query that did not handle the Nullable Columns. This write up also illustration on how to convert the Dataset to a list

Changed the code to
List <> output = new List <> ( ) ;
output = (from b in bBaseDataSet.bTable
select new BOuput
{
A = b.a,
B = b.Field <> ("bColumnName"), //remove the extra spaces added
C = b.Field <> ("cColumnName"),
D = b.d
}
).ToList();

Thursday, April 29, 2010

Boot Camp

1. Reverse a singly linked list
// LinkList.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

struct list
{
int month;
struct list *next;
};
typedef struct list node;
void init(node* record)
{
record->next=NULL;
}
void addnode(node* record,int d)
{
node* fresh;
fresh=(node *)malloc(sizeof(node));
fresh->month=d;
fresh->next=record->next;
record->next=fresh;
}
void print(node *record)
{
node* temp;
temp=(node *)malloc(sizeof(node));
for(temp=record->next;temp;temp=temp->next)
printf(" %d",temp->month);
}

void reverse(node* record)
{
node* temp;
node* temp1;
node* temp2;
temp=(node *)malloc(sizeof(node));
temp1=(node *)malloc(sizeof(node));
temp2=(node *)malloc(sizeof(node));
temp=record;
temp1=temp->next;
temp2=temp1->next;
temp->next->next=NULL;
while(temp2!=NULL)
{
temp=temp1;
temp1=temp2;
temp2=temp1->next;
temp1->next=temp;
}
record->next=temp1;
}




int _tmain(int argc, _TCHAR* argv[])
{
node* start;
start=(node *) malloc(sizeof(node));
init(start);
int i=0;
for(i=5;i>=0;i--)
addnode(start,i);
print(start);
reverse(start);
printf("\n");
print(start);
printf("\n");
return 0;
}
2. Copy link list to another list
// Copy List
node* CopyList(node* head)
{
node* current = head; // used to iterate over the original list
node* newList = NULL; // head of the new list
node* tail = NULL; // kept pointing to the last node in the new list

while (current != NULL)
{
if (newList == NULL)
{
// special case for the first new node
newList = (node *)malloc(sizeof(node));
newList->month = current->month;
newList->next = NULL;
tail = newList;
}
else
{
tail->next = (node *)malloc(sizeof(node));
tail = tail->next;
tail->month = current->month;
tail->next = NULL;
}
current = current->next;
}
return(newList);
}
3. Length of the list
int Length(node* head)
{
node* current = head;
int count = 0;
while (current->next != NULL)
{
count++;
current = current->next;
}
return count;
}

4. Check if there a loop in the list
bool hasLoop(node* startNode)
{
node* slowNode = startNode;
node* fastNode = startNode;
node* fasterNode = startNode;

while (slowNode && fasterNode == fasterNode->next && fasterNode == fastNode->next)
{
if (slowNode == fastNode || slowNode == fasterNode)
return true;
slowNode = slowNode->next;
}
return false;
}

5. Delete a node in a doubly linked list
void deleteNode(node *n)
{
node *np = n->prev;
node *nn = n->next;
np->next = n->next;
nn->prev = n->prev;
delete n;
}

6. Print data from a binary tree
/*
Given a binary search tree, print out
its data elements in increasing
sorted order.
*/
void printTree(struct node* node) {
if (node == NULL) return;
printTree(node->left);
printf("%d ", node->data);
printTree(node->right);
}

7. What is Binary tree
struct node
{
int key_value;
struct node *left;
struct node *right;
};


struct node *search(int key, struct node *leaf)
{
if( leaf != 0 )
{
if(key==leaf->key_value)
{
return leaf;
}
else if(keykey_value)
{
return search(key, leaf->left);
}
else
{
return search(key, leaf->right);
}
}
else return 0;
}
/*
Helper function that allocates a new node
with the given data and NULL left and right
pointers.
*/
struct node* NewNode(int data) {
struct node* node = new(struct node); // "new" is like "malloc"
node->data = data;
node->left = NULL;
node->right = NULL;

return(node);
}

/*
Give a binary search tree and a number, inserts a new node
with the given number in the correct place in the tree.
Returns the new root pointer which the caller should
then use (the standard trick to avoid using reference
parameters).
*/
struct node* insert(struct node* node, int data) {
// 1. If the tree is empty, return a new, single node
if (node == NULL) {
return(newNode(data));
}
else {
// 2. Otherwise, recur down the tree
if (data <= node->data) node->left = insert(node->left, data);
else node->right = insert(node->right, data);

return(node); // return the (unchanged) node pointer
}
}

8. Factorial of number
//
// recursive version
//
int Factorial( int Num )
{
if ( num > 0 )
return Num * Factorial ( Num –1 );
else
return 1;
}
//
// iterative version
//
int Factorial( int Num )
{
int I
int result = 1;

for ( I= Num; I > 0; I-- )
{
result = result * I;
}

return result;
}

9. Fibonacci of a number
int fib( n ) // recursive version
{
if ( n < 2 )
return 1;
else
return fib ( n –1 ) + fib ( n –2 );

}

int fib( n ) //iterative version
{
int f1 =1, f2 = 1;

if ( n < 2 )
return 1;
for ( i = 1; i < N; i++)
{
f = f1 + f2;
f1= f2;
f = f1;
}
return f;
}

10. Find the last occurrence of a character in the string
char *lastchar(char *String, char ch)
{
char *pStr = NULL;

// traverse the entire string

while( * String ++ != NULL )
{
if( *String == ch )
pStr = String;
}

return pStr;
}


11. Return nth node from the end of the linked list in one pass
node* GetNthNode ( node* Head , int NthNode )
{
node * pNthNode = NULL;
node * pTempNode = NULL;
int nCurrentElement = 0;

for ( pTempNode = Head; pTempNode != NULL; pTempNode = pTempNode->next )
{
nCurrentElement++;
if ( nCurrentElement - NthNode == 0 )
{
pNthNode = Head;
}
else
if ( nCurrentElement - NthNode > 0)
{
pNthNode = pNthNode ->next;
}
}
if (pNthNode )
{
return pNthNode;
}
else
return NULL;
}

12. Delete a node n, if you don’t know the head of the list
Q: What is the difference between 'BOOL' and 'bool'?
A: 'bool' is a built-in C++ type while 'BOOL' is a Microsoft specific type that is defined as an 'int'. You can find it in 'windef.h':
Code:
typedef int BOOL;

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif
The only possible values for a 'bool' are 'true' and 'false', whereas for 'BOOL' you can use any 'int' value, though 'TRUE' and 'FALSE' macros are defined in 'windef.h' header.

13. Search for a value in sorted array
C++
/*
* searches for a value in sorted array
* arr is an array to search in
* value is searched value
* left is an index of left boundary
* right is an index of right boundary
* returns position of searched value, if it presents in the array
* or -1, if it is absent
*/
int binarySearch(int arr[], int value, int left, int right)
{
while (left <= right)
{
int middle = (left + right) / 2;
if (arr[middle] == value)
return middle;
else if (arr[middle] > value)
right = middle - 1;
else
left = middle + 1;
}
return -1;
}

14.
Q: Four people need to cross a rickety rope bridge to get back to their camp at night. Unfortunately, they only have one flashlight and it only has enough light left for seventeen minutes. The bridge is too dangerous to cross without a flashlight, and it’s only strong enough to support two people at any given time. Each of the campers walks at a different speed. One can cross the bridge in 1 minute, another in 2 minutes, the third in 5 minutes, and the slow poke takes 10 minutes to cross. How do the campers make it across in 17 minutes?

A: A(1), B(2), C(5), D(10)

1. A & B cross together. They take 2 minutes
2. A come back to start point. He takes 1 more min.
3. So far 3 minutes invested in total
4. C and D start together. Reach in 10 minutes. So total 13 minutes invested so far
5. B who is at the far end, take the torch and comes back to start point. He needs 2 min
6. So far far 15 min invested
7. A and B start together, reach the far end in 2 min
8. Total 17 min invested.

15.
Q: How would you find a cycle in a linked list? Try to do it in O(n) time. Try it using constant amount of memory.
A: p2 is guaranteed to reach the end of the list before p1 and every link will be tested by the while condition so no chance of access violation. Also, incrementing p2 by 2 and p1 by 1 is the fastest way of finding the cycle. In general if p1 is incremented by 'n' and p2 by 'm', ('n' not == 'm'), then if we number the nodes in the cycle from 0 to k-1 (k is the number of nodes in the cycle), then p1 will take values given by i*n (mod k) and p2 will take values i*m (mod k). These will collide every n*m iterations. Clearly, n*m is smallest for n==1 and m==2.

bool HasCycle(Node *pHeadNode)
{
Node *p1, *p2;
p1 = p2 = pHeadNode;
while (p2 && p2->Next) {
p1 = p1->Next;
p2 = p2->Next->Next;
if (p1 == p2)
return true;
}
return false;
}

16.
Q: Implement an algorithm to reverse a singly linked list. (with and without recursion)

Node *RevSList(Node *pCur, Node *pRev) {
if (!pCur) return pRev;
Node *pNext = pCur->Next;
pCur->Next = pRev;
pRev = pCur;
return (RevSList(pNext, pRev));
}

Node * RevSList(Node *pCur) {
Node *pRev = NULL;
while (pCur)
{
Node *pNext = pCur->Next;
pCur->Next = pRev;
pRev = pCur;
pCur = pNext;
}
return pRev;
}

17. Delete a node in Single Link List
node *DelSLLNode(node *pDelete, node *pHead)
{
if (pHead == pDelete)
return (pHead = pHead->next);

node *pPrev = pHead;
for ( ; pPrev->next; pPrev = pPrev->next)
{
if (pPrev->next == pDelete)
{
pPrev->next = pPrev->next->next;
break;
}
}
return pHead;
}

18.
One train leaves Los Angeles at 15 MPH heading for New York. Another train leaves from New York at 20mph heading for Los Angeles on the same track. If a bird, flying at 25mph, leaves from Los Angeles at the same time as the train and flies back and forth between the two trains until they collide, how far will the bird have traveled?
If distance is X miles between NY and LA, then it takes X/(15+20) hours for the trains to collide, and bird will have travelled 25X/(15+20) = 5X/7 miles in that time.

19.
You have 12 balls. All of them are identical except one, which is either heavier or lighter than the rest - it is either hollow while the rest are solid, or solid while the rest are hollow. You have a simple two-armed scale, and are permitted three weighings. Can you identify the odd ball, and determine whether it is hollow or solid.
Let the balls be numbered 1 to 12. Firstly, put 1-4 on one side and 5-8 on other side. If both are equal then one of 9-12 is odd. Then second try, weigh 9-10 vs 1-2, if equal, one of 11-12 is bad, else 9-10 is bad. Testing which one is bad can be done by (third try) weighing 11 or 9, respectively, with good ball 1. It also gives whether the odd ball is heavy or light.

20.
You have 5 jars of pills. Each pill weighs 10 gram, except for contaminated pills contained in one jar, where each pill weighs 9 gm. Given a scale, how could you tell which jar had the contaminated pills in just one measurement?
Take one pill from first, two from second, three from third and so on. Total pills are n(n+1)/2 and should weigh 10n(n+1)/2. If it weighs x gm less than that then the x'th jar is contaminated, since we took x pills from that jar which weighed 1 gm less.

21. Write a function that finds repeating characters in a string
/* Returns an array of size 256 containg count
of characters in the passed char array
*/
int *getCharCountArray(char *str)
{
int *count = (int *)calloc(sizeof(int), NO_OF_CHARS);
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return count;
}

/* The function returns index of first non-repeating
character in a string. If all characters are repeating
then reurns -1
*/
int firstNonRepeating(char *str)
{
int *count = getCharCountArray(str);
int index = -1, i;

for (i = 0; *(str+i); i++)
{
if(count[*(str+i)] == 1)
{
index = i;
break;
}
}
return index;
}

int _tmain(int argc, _TCHAR* argv[])
{

char str[] = "geeksforgeeks";
int index = firstNonRepeating(str);
if(index == -1)
printf("Either all characters are repeating or string is empty");
else
printf("First non-repeating character is %c", str[index]);
return 0;
}

22. Format the paragraph having multiple statements (ended with a “.” Period). For instance “This is one completed statement.The other just started with no space,so I’ll pay you $10.0 to format it.”

23. Implement Undo, Redo of MS Word

Wednesday, February 17, 2010

Using TRY...CATCH in Transact-SQL

reference: http://msdn.microsoft.com/en-us/library/ms179296(SQL.90).aspx

Errors in Transact-SQL code can be processed by using a TRY…CATCH construct similar to the exception-handling features of the Microsoft Visual C++ and Microsoft Visual C# languages. A TRY…CATCH construct consists of two parts: a TRY block and a CATCH block. When an error condition is detected in a Transact-SQL statement that is inside a TRY block, control is passed to a CATCH block where the error can be processed.


After the CATCH block handles the exception, control is then transferred to the first Transact-SQL statement that follows the END CATCH statement. If the END CATCH statement is the last statement in a stored procedure or trigger, control is returned to the code that invoked the stored procedure or trigger. Transact-SQL statements in the TRY block following the statement that generates an error will not be executed.


If there are no errors inside the TRY block, control passes to the statement immediately after the associated END CATCH statement. If the END CATCH statement is the last statement in a stored procedure or trigger, control is passed to the statement that invoked the stored procedure or trigger.


A TRY block starts with the BEGIN TRY statement and ends with the END TRY statement. One or more Transact-SQL statements can be specified between the BEGIN TRY and END TRY statements.


A TRY block must be followed immediately by a CATCH block. A CATCH block starts with the BEGIN CATCH statement and ends with the END CATCH statement. In Transact-SQL, each TRY block is associated with only one CATCH block.







When you use the TRY…CATCH construct, consider the following guidelines and suggestions:



  • Each TRY…CATCH construct must be inside a single batch, stored procedure, or trigger. For example, you cannot place a TRY block in one batch and the associated CATCH block in another batch. The following script would generate an error:

    id="ctl00_MTCS_main_ctl51_ctl00_ctl00_">













    BEGIN TRY
    SELECT *
    FROM sys.messages
    WHERE message_id = 21;
    END TRY
    GO
    -- The previous GO breaks the script into two batches,
    -- generating syntax errors. The script runs if this GO
    -- is removed.
    BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber;
    END CATCH;
    GO






  • A TRY block must be immediately followed by a CATCH block.


  • TRY…CATCH constructs can be nested. This means that TRY…CATCH constructs can be placed inside other TRY and CATCH blocks. When an error occurs within a nested TRY block, program control is transferred to the CATCH block that is associated with the nested TRY block.


  • To handle an error that occurs within a given CATCH block, write a TRY…...CATCH block within the specified CATCH block.


  • Errors that have a severity of 20 or higher that cause the Database Engine to close the connection will not be handled by the TRY…CATCH block. However, TRY…CATCH will handle errors with a severity of 20 or higher as long as the connection is not closed.


  • Errors that have a severity of 10 or lower are considered warnings or informational messages, and are not handled by TRY…CATCH blocks.


  • Attentions will terminate a batch even if the batch is within the scope of a TRY…CATCH construct. This includes an attention sent by the Microsoft Distributed Transaction Coordinator (MS DTC) when a distributed transaction fails. MS DTC manages distributed transactions.

    ms179296.note(en-US,SQL.90).gifNote:

    If a distributed transaction executes within the scope of a TRY block and an error occurs, execution is transferred to the associated CATCH block. The distributed transaction enters an uncommittable state. Execution within the CATCH block may be interrupted by the Microsoft Distributed Transaction Coordinator which manages distributed transactions. When the error occurs, MS DTC asynchronously notifies all servers participating in the distributed transaction, and terminates all tasks involved in the distributed transaction. This notification is sent in the form of an attention, which is not handled by a TRY…CATCH construct, and the batch is ended. When a batch finishes running, 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 that indicates an uncommittable transaction was detected and rolled back For more information about distributed transactions, see Distributed Transactions (Database Engine).





Error Functions


TRY…CATCH uses the following error functions to capture error information:



  • ERROR_NUMBER() returns the error number.


  • ERROR_MESSAGE() returns the complete text of the error message. The text includes the values supplied for any substitutable parameters such as lengths, object names, or times.


  • ERROR_SEVERITY() returns the error severity.


  • ERROR_STATE() returns the error state number.


  • ERROR_LINE() returns the line number inside the routine that caused the error.


  • ERROR_PROCEDURE() returns the name of the stored procedure or trigger where the error occurred.


Error information is retrieved by using these functions from anywhere in the scope of the CATCH block of a TRY…CATCH construct. The error functions will return NULL if called outside the scope of a CATCH block. Error functions can be referenced inside a stored procedure and can be used to retrieve error information when the stored procedure is executed in the CATCH block. By doing this, you do not have to repeat the error handling code in every CATCH block. In the follow code example, the SELECT statement in the TRY block will generate a divide-by-zero error. The error will be handled by the CATCH block, which uses a stored procedure to return error information.















USE AdventureWorks;
GO

-- Verify that the stored procedure does not exist.
IF OBJECT_ID ('usp_GetErrorInfo', 'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO

-- Create a procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() as ErrorState,
ERROR_PROCEDURE() as ErrorProcedure,
ERROR_LINE() as ErrorLine,
ERROR_MESSAGE() as ErrorMessage;
GO

BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute the error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
GO






Compile and Statement-level Recompile Errors


There are two types of errors that will not be handled by TRY…CATCH if the error occurs in the same execution level as the TRY…CATCH construct:



  • Compile errors, such as syntax errors that prevent a batch from executing.


  • Errors that occur during statement-level recompilation, such as object name resolution errors that happen after compilation due to deferred name resolution.


When the batch, stored procedure, or trigger that contains the TRY…CATCH construct generates one of these errors, the TRY…CATCH construct does not handle these errors. These errors will return to the application or batch that called the error-generating routine. For example, the following code example shows a SELECT statement that causes a syntax error. If this code is executed in the SQL Server Management Studio Query Editor, execution will not start because the batch fails to compile. The error will be returned to the Query Editor and will not get caught by TRY…CATCH.















USE AdventureWorks;
GO

BEGIN TRY
-- This PRINT statement will not run because the batch
-- does not begin execution.
PRINT N'Starting execution';

-- This SELECT statement contains a syntax error that
-- stops the batch from compiling successfully.
SELECT ** FROM HumanResources.Employee;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO





Unlike the syntax error in the previous example, an error that occurs during statement-level recompilation will not prevent the batch from compiling, but it will terminate the batch as soon as recompilation for the statement fails. For example, if a batch has two statements and the second statement references a table that does not exist, deferred name resolution causes the batch to compile successfully and start execution without binding the missing table to the query plan until that statement is recompiled. The batch stops running when it gets to the statement that references the missing table and returns an error. This type of error will not be handled by a TRY…CATCH construct at the same level of execution at which the error occurred. The following example demonstrates this behavior.















USE AdventureWorks;
GO

BEGIN TRY
-- This PRINT statement will run because the error
-- occurs at the SELECT statement.
PRINT N'Starting execution';

-- This SELECT statement will generate an object name
-- resolution error because the table does not exist.
SELECT * FROM NonExistentTable;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO





You can use TRY…CATCH to handle errors that occur during compilation or statement-level recompilation by executing the error-generating code in a separate batch within the TRY block. For example, you do this by placing the code in a stored procedure or by executing a dynamic Transact-SQL statement using sp_executesql. This allows TRY…CATCH to catch the error at a higher level of execution than the error occurrence. For example, the following code shows a stored procedure that generates an object name resolution error. The batch that contains the TRY…CATCH construct is executing at a higher level than the stored procedure; and the error, which occurs at a lower level, is caught.
















USE AdventureWorks;
GO

-- Verify that the stored procedure does not already exist.
IF OBJECT_ID ('usp_MyError', 'P') IS NOT NULL
DROP PROCEDURE usp_MyError;
GO

CREATE PROCEDURE usp_MyError
AS
-- This SELECT statement will generate
-- an object name resolution error.
SELECT * FROM NonExistentTable;
GO

BEGIN TRY
-- Run the stored procedure.
EXECUTE usp_MyError;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO






Here is the result set.














ErrorNumber ErrorMessage
----------- ---------------------------------------
208 Invalid object name 'NonExistentTable'.





For more information, see Deferred Name Resolution and Compilation and the "Recompiling Execution Plans" section in Execution Plan Caching and Reuse.



Uncommittable Transactions


Inside a TRY…CATCH construct, transactions can enter a state in which the transaction remains open but cannot be committed. The transaction cannot perform any action that would generate a write to the transaction log, such as modifying data or trying to roll back to a savepoint. However, in this state, the locks acquired by the transaction are maintained, and the connection is also kept open. The effects of the transaction are not reversed until a ROLLBACK statement is issued, or until the batch ends and the transaction is automatically rolled back by the Database Engine. 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 that indicates an uncommittable transaction was detected and rolled back.


A transaction enters an uncommittable state inside a TRY block when an error occurs that would otherwise have ended the transaction. For example, most errors from a data definition language (DDL) statement (such as CREATE TABLE), or most errors that occur when SET XACT_ABORT is set to ON, terminate the transaction outside a TRY block but make a transaction uncommittable inside a TRY block.


The code in a CATCH block should test for the state of a transaction by using the XACT_STATE function. XACT_STATE returns a -1 if the session has an uncommittable transaction. The CATCH block must not perform any actions that would generate writes to the log if XACT_STATE returns a -1. The following code example generates an error from a DDL statement and uses XACT_STATE to test the state of a transaction in order to take the most appropriate action.
















USE AdventureWorks;
GO

-- Verify that the table does not exist.
IF OBJECT_ID (N'my_books', N'U') IS NOT NULL
DROP TABLE my_books;
GO

-- Create table my_books.
CREATE TABLE my_books
(
Isbn int PRIMARY KEY,
Title NVARCHAR(100)
);
GO

BEGIN TRY
BEGIN TRANSACTION;
-- This statement will generate an error because the
-- column author does not exist in the table.
ALTER TABLE my_books
DROP COLUMN author;
-- If the DDL statement succeeds, commit the transaction.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage;

-- Test XACT_STATE for 1 or -1.
-- XACT_STATE = 0 means 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 active and valid.
IF (XACT_STATE()) = 1
BEGIN
PRINT
N'The transaction is committable. ' +
'Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
GO






Handling Deadlocks


TRY…CATCH can be used to handle deadlocks. The 1205 deadlock victim error can be caught by the CATCH block and the transaction can be rolled back until the threads become unlocked. For more information about deadlocking, see Deadlocking.


The following example shows how TRY…CATCH can be used to handle deadlocks. This first section creates a table that will be used to demonstrate a deadlock state and a stored procedure that will be used to print error information.
















USE AdventureWorks;
GO

-- Verify that the table does not exist.
IF OBJECT_ID (N'my_sales',N'U') IS NOT NULL
DROP TABLE my_sales;
GO

-- Create and populate the table for deadlock simulation.
CREATE TABLE my_sales
(
Itemid INT PRIMARY KEY,
Sales INT not null
);
GO

INSERT my_sales (itemid, sales) VALUES (1, 1);
INSERT my_sales (itemid, sales) VALUES (2, 1);
GO

-- Verify that the stored procedure for error printing
-- does not exist.
IF OBJECT_ID (N'usp_MyErrorLog',N'P') IS NOT NULL
DROP PROCEDURE usp_MyErrorLog;
GO

-- Create a stored procedure for printing error information.
CREATE PROCEDURE usp_MyErrorLog
AS
PRINT
'Error ' + CONVERT(VARCHAR(50), ERROR_NUMBER()) +
', Severity ' + CONVERT(VARCHAR(5), ERROR_SEVERITY()) +
', State ' + CONVERT(VARCHAR(5), ERROR_STATE()) +
', Line ' + CONVERT(VARCHAR(5), ERROR_LINE());
PRINT
ERROR_MESSAGE();
GO





The following code scripts for session 1 and session 2 run simultaneously in two separate SQL Server Management Studio connections. Both sessions try to update the same rows in the table. One of the sessions will succeed with the update operation during the first attempt, and the other session will be selected as the deadlock victim. The deadlock victim error will cause execution to jump to the CATCH block and the transaction will enter an uncommittable state. Inside the CATCH block, the deadlock victim can roll back the transaction and retry updating the table until the update succeeds or the retry limit is reached, whichever happens first.



Session 1

Session 2















USE AdventureWorks;
GO

-- Declare and set variable
-- to track number of retries
-- to try before exiting.
DECLARE @retry INT;
SET @retry = 5;

-- Keep trying to update
-- table if this task is
-- selected as the deadlock
-- victim.
WHILE (@retry > 0)
BEGIN
BEGIN TRY
BEGIN TRANSACTION;

UPDATE my_sales
SET sales = sales + 1
WHERE itemid = 1;

WAITFOR DELAY '00:00:13';

UPDATE my_sales
SET sales = sales + 1
WHERE itemid = 2;

SET @retry = 0;

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Check error number.
-- If deadlock victim error,
-- then reduce retry count
-- for next update retry.
-- If some other error
-- occurred, then exit
-- retry WHILE loop.
IF (ERROR_NUMBER() = 1205)
SET @retry = @retry - 1;
ELSE
SET @retry = -1;

-- Print error information.
EXECUTE usp_MyErrorLog;

IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
END CATCH;
END; -- End WHILE loop.
GO


















USE AdventureWorks;
GO

-- Declare and set variable
-- to track number of retries
-- to try before exiting.
DECLARE @retry INT;
SET @retry = 5;

--Keep trying to update
-- table if this task is
-- selected as the deadlock
-- victim.
WHILE (@retry > 0)
BEGIN
BEGIN TRY
BEGIN TRANSACTION;

UPDATE my_sales
SET sales = sales + 1
WHERE itemid = 2;

WAITFOR DELAY '00:00:07';

UPDATE my_sales
SET sales = sales + 1
WHERE itemid = 1;

SET @retry = 0;

COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Check error number.
-- If deadlock victim error,
-- then reduce retry count
-- for next update retry.
-- If some other error
-- occurred, then exit
-- retry WHILE loop.
IF (ERROR_NUMBER() = 1205)
SET @retry = @retry - 1;
ELSE
SET @retry = -1;

-- Print error information.
EXECUTE usp_MyErrorLog;

IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
END CATCH;
END; -- End WHILE loop.
GO







TRY…CATCH with RAISERROR


RAISERROR can be used in either the TRY or CATCH block of a TRY…CATCH construct to affect error-handling behavior.


RAISERROR that has a severity of 11 to 19 executed inside a TRY block causes control to transfer to the associated CATCH block. RAISERROR that has a severity of 11 to 19 executed inside a CATCH block returns an error to the calling application or batch. In this way, RAISERROR can be used to return information to the caller about the error that caused the CATCH block to execute. Error information provided by the TRY…CATCH error functions can be captured in the RAISERROR message, including the original error number; however, the error number for RAISERROR must be >= 50000.


RAISERROR that has a severity 10 or lower returns an informational message to the calling batch or application without invoking a CATCH block.


RAISERROR that has a severity 20 or higher closes the database connection without invoking the CATCH block.


The following code example shows how RAISERROR can be used inside a CATCH block to return the original error information to the calling application or batch. The stored procedure usp_GenerateError executes a DELETE statement inside a TRY block that generates a constraint violation error. The error causes execution to transfer to the associated CATCH block inside usp_GenerateError where the stored procedure usp_RethrowError is executed to raise the constraint violation error information using RAISERROR. This error generated by RAISERROR is returned to the calling batch where usp_GenerateError was executed and causes execution to transfer to the associated CATCH block in the calling batch.


ms179296.note(en-US,SQL.90).gifNote:

RAISERROR can generate errors with state from 1 through 127 only. Because the Database Engine might raise errors with state 0, we recommend that you check the error state returned by ERROR_STATE before passing it as a value to the state parameter of RAISERROR.

















USE AdventureWorks;
GO

-- Verify that stored procedure does not exist.
IF OBJECT_ID (N'usp_RethrowError',N'P') IS NOT NULL
DROP PROCEDURE usp_RethrowError;
GO

-- Create the stored procedure to generate an error using
-- RAISERROR. The original error information is used to
-- construct the msg_str for RAISERROR.
CREATE PROCEDURE usp_RethrowError AS
-- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
RETURN;

DECLARE
@ErrorMessage NVARCHAR(4000),
@ErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure NVARCHAR(200);

-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');

-- Build the message string that will contain original
-- error information.
SELECT @ErrorMessage =
N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +
'Message: '+ ERROR_MESSAGE();

-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR
(
@ErrorMessage,
@ErrorSeverity,
1,
@ErrorNumber, -- parameter: original error number.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
GO

-- Verify that stored procedure does not exist.
IF OBJECT_ID (N'usp_GenerateError',N'P') IS NOT NULL
DROP PROCEDURE usp_GenerateError;
GO

-- Create a stored procedure that generates a constraint violation
-- error. The error is caught by the CATCH block where it is
-- raised again by executing usp_RethrowError.
CREATE PROCEDURE usp_GenerateError
AS
BEGIN TRY
-- A FOREIGN KEY constraint exists on the table. This
-- statement will generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
-- Call the procedure to raise the original error.
EXEC usp_RethrowError;
END CATCH;
GO

-- In the following batch, an error occurs inside
-- usp_GenerateError that invokes the CATCH block in
-- usp_GenerateError. RAISERROR inside this CATCH block
-- generates an error that invokes the outer CATCH
-- block in the calling batch.
BEGIN TRY -- outer TRY
-- Call the procedure to generate an error.
EXECUTE usp_GenerateError;
END TRY
BEGIN CATCH -- Outer CATCH
SELECT
ERROR_NUMBER() as ErrorNumber,
ERROR_MESSAGE() as ErrorMessage;
END CATCH;
GO






Changing the Flow of Execution


To change the flow of execution, GOTO can be used within a TRY block or a CATCH block. GOTO can also be used to exit a TRY block or a CATCH block; however, GOTO cannot be used to enter a TRY block or a CATCH block.











The AdventureWorks sample database includes an error-handling solution designed to log information about errors that are caught by the CATCH block of a TRY…CATCH construct that can later be queried or analyzed.



dbo.ErrorLog Table


The ErrorLog table records information about an error number, error severity, error state, name of the stored procedure or trigger where the error occurred, line number at which the error occurred, and the complete text of the error message. It also records the date and time at which the error occurred, and the user name which executed the error-generating routine. This table is populated when the stored procedure uspLogError is executed in the scope of the CATCH block of a TRY…CATCH construct. For more information, see ErrorLog Table (AdventureWorks).



dbo.uspLogError


The stored procedure uspLogError logs error information in the ErrorLog table about the error that caused execution to transfer to the CATCH block of a TRY…CATCH construct. For uspLogError to insert error information into the ErrorLog table, the following conditions must exist:




  • uspLogError is executed within the scope of a CATCH block.


  • If the current transaction is in an uncommittable state, the transaction is rolled back before executing uspLogError.


The output parameter @ErrorLogID of uspLogError returns the ErrorLogID of the row inserted by uspLogError into the ErrorLog table. The default value of @ErrorLogID is 0. The following example shows the code for uspLogError. For more information, see Stored Procedures in AdventureWorks.
















CREATE PROCEDURE [dbo].[uspLogError] 
@ErrorLogID [int] = 0 OUTPUT -- Contains the ErrorLogID of the row inserted
-- by uspLogError in the ErrorLog table.

AS
BEGIN
SET NOCOUNT ON;

-- Output parameter value of 0 indicates that error
-- information was not logged.
SET @ErrorLogID = 0;

BEGIN TRY
-- Return if there is no error information to log.
IF ERROR_NUMBER() IS NULL
RETURN;

-- Return if inside an uncommittable transaction.
-- Data insertion/modification is not allowed when
-- a transaction is in an uncommittable state.
IF XACT_STATE() = -1
BEGIN
PRINT 'Cannot log error since the current transaction is in an uncommittable state. '
+ 'Rollback the transaction before executing uspLogError in order to successfully log error information.';
RETURN;
END;

INSERT [dbo].[ErrorLog]
(
[UserName],
[ErrorNumber],
[ErrorSeverity],
[ErrorState],
[ErrorProcedure],
[ErrorLine],
[ErrorMessage]
)
VALUES
(
CONVERT(sysname, CURRENT_USER),
ERROR_NUMBER(),
ERROR_SEVERITY(),
ERROR_STATE(),
ERROR_PROCEDURE(),
ERROR_LINE(),
ERROR_MESSAGE()
);

-- Pass back the ErrorLogID of the row inserted
SELECT @ErrorLogID = @@IDENTITY;
END TRY
BEGIN CATCH
PRINT 'An error occurred in stored procedure uspLogError: ';
EXECUTE [dbo].[uspPrintError];
RETURN -1;
END CATCH
END;






dbo.uspPrintError


The stored procedure uspPrintError prints information about the error that caused execution to transfer to the CATCH block of a TRY…CATCH construct. uspPrintError should be executed in the scope of a CATCH block; otherwise, the procedure returns without printing any error information. The following example shows the code for uspPrintError. For more information, see Stored Procedures in AdventureWorks.















CREATE PROCEDURE [dbo].[uspPrintError] 
AS
BEGIN
SET NOCOUNT ON;

-- Print error information.
PRINT 'Error ' + CONVERT(varchar(50), ERROR_NUMBER()) +
', Severity ' + CONVERT(varchar(5), ERROR_SEVERITY()) +
', State ' + CONVERT(varchar(5), ERROR_STATE()) +
', Procedure ' + ISNULL(ERROR_PROCEDURE(), '-') +
', Line ' + CONVERT(varchar(5), ERROR_LINE());
PRINT ERROR_MESSAGE();
END;






Error-handling Example


The following example demonstrates the AdventureWorks error-handling solution. The code inside the TRY block tries to delete the record with ProductID 980 in the Production.Product table. A FOREIGN KEY constraint on the table prevents the DELETE statement from succeeding and a constraint violation error is generated. This error causes execution to transfer to the CATCH block. Inside the CATCH block, the following actions occur:




  • uspPrintError prints the error information.


  • After the transaction is rolled back, uspLogError enters the error information in the ErrorLog table and returns the ErrorLogID of the inserted row into the @ErrorLogID OUTPUT parameter.
















USE AdventureWorks;
GO

-- Variable to store ErrorLogID value of the row
-- inserted in the ErrorLog table by uspLogError
DECLARE @ErrorLogID INT;

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 operation succeeds, commit the transaction.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Call procedure to print error information.
EXECUTE dbo.uspPrintError;

-- Roll back any active or uncommittable transactions before
-- inserting information in the ErrorLog.
IF XACT_STATE() <> 0
BEGIN
ROLLBACK TRANSACTION;
END

EXECUTE dbo.uspLogError @ErrorLogID = @ErrorLogID OUTPUT;
END CATCH;

-- Retrieve logged error information.
SELECT * FROM dbo.ErrorLog WHERE ErrorLogID = @ErrorLogID;
GO






Nested Error-handling Example


The following example shows using nested TRY…CATCH constructs.
















BEGIN TRY
BEGIN TRY
SELECT CAST('invalid_date' AS datetime)
END TRY
BEGIN CATCH
PRINT 'Inner TRY error number: ' +
CONVERT(varchar,ERROR_NUMBER()) + ' on line: ' +
CONVERT(varchar, ERROR_LINE())
END CATCH
SELECT CAST('invalid_int' AS int)
END TRY
BEGIN CATCH
PRINT 'Outer TRY error mumber: ' + CONVERT(varchar,ERROR_NUMBER())+
' on line: ' + CONVERT(varchar, ERROR_LINE())
END CATCH






Here is the result set.



Inner TRY error number: 241 on line: 3



Outer TRY error number: 245 on line: 9

How to: Use the Values of Parent Variables in a Child Package

How to: Use the Values of Parent Variables in a Child Package
reference from MSDN: http://technet.microsoft.com/en-us/library/ms345179.aspx

To add a parent package configuration to a child package
1. If it is not already open, open the child package in Business Intelligence Development Studio.
2. Click anywhere on the design surface of the Control Flow tab.
3. On the SSIS menu, click Package Configurations.
4. In the Package Configuration Organizer dialog box, select Enable package configuration, and then click Add.
5. On the welcome page of the Package Configuration Wizard, click Next.
6. On the Select Configuration Type page, in the Configuration type list, select Parent package variable and do one of the following:
Select Specify configuration settings directly, and then in the Parent variable box, provide the name of the variable in the parent package to use in the configuration.
Important:
Variable names are case sensitive.
Select or Configuration location is stored in an environment variable, and then in the Environment variable list, select the environmentvariable that contains the name of the variable.
7. Click Next.
8. On the Select Target Property page, expand the Variable node, and expand the Properties node of the variable to configure, and then click the property to be set by the configuration.
9. Click Next.
10. On the Completing the Wizard page, optionally, modify the default name of the configuration and review the configuration information.
11. Click Finish to complete the wizard and return to the Package Configuration Organizer dialog box.
12. In the Package Configuration Organizer dialog box, the Configuration box lists the new configuration.
13. Click Close.

Monday, January 4, 2010

SSIS: Working with Parameters in the Execute SQL Task (ADO.NET)


Using Parameters with Stored Procedures

reference: MSDN

Using Parameters with ADO.NET and ADO Connection ManagersADO.NET and ADO connection managers have specific requirements for SQL commands that use parameters:
ADO.NET connection managers require that the SQL command use parameter names as parameter markers. This means that variables can be mapped directly to parameters. For example, the variable @varName is mapped to the parameter named @parName and provides a value to the parameter @parName.


ADO.NET Set IsQueryStoreProcedure is set to True.


To provide values to parameters, variables are mapped to parameter names. Then, the Execute SQL task uses the ordinal value of the parameter name in the parameter list to load values from variables to parameters.

Wednesday, December 23, 2009

SSIS: How to fix 'Can't get lock on variable or deadlock occured' error when you are trying to handle exception using Script Component

Issue:

If you've a Script Component in the Control Flow, which is writing to LogFile (DtsVariable), and an exception occurs, and if you Exception Handling Component also using the same LogFile (DtsVariable) to log error to the file then you enter a deadlock scenario. It happened because the Script component was still holding the lock but flow jumped to the Exception Handler. All that needs to be done was to un lock variable before we jump to the Exception Handler Block.

Resolution:

Try

...

Catch ex As Exception
Logfile.WriteLine("Exception Occured: " + ex.Message)
Dts.Variables.Unlock()
Dts.TaskResult = Dts.Results.Failure
Throw New Exception(ex.Message)
End Try

Additional Reading:

Reusable Functions for Reading and Writing Variables in SSIS Script Tasks

http://www.developerdotstar.com/community/node/512

Thursday, December 3, 2009

Partitioned Tables and Indexes in SQL Server 2005

Partitioned Tables and Indexes in SQL Server 2005
reference: http://msdn.microsoft.com/en-us/library/ms345146(SQL.90).aspx

This article is simple abstract of what has to be done. If you've a scenario wherein you need to partition a large table Orders based on for instance order date (datetime datatype). We can either partitioned the table for each month, Quarter or Half yearly depending on what is expected requirement.
Step1
-- add filegroup to the database
-- first filegroup
ALTER DATABASE TestPart ADD FILEGROUP [2007HY1]
-- second filegroup
ALTER DATABASE TestPart ADD FILEGROUP [2007HY2]

Step 2
-- add files to the filegroup
-- add first file to the file group
ALTER DATABASE TestPart
ADD FILE
(NAME = N'2007HY1',
FILENAME = N'C:\TestPart\2007HY1.ndf',
SIZE = 5 MB,
FILEGROWTH = 20%)
TO FILEGROUP [2007HY1]
-- add second file to the file group
ALTER DATABASE TestPart
ADD FILE
(NAME = N'2007HY2',
FILENAME = N'C:\TestPart\2007HY2.ndf',
SIZE = 5 MB,
FILEGROWTH = 20%)
TO FILEGROUP [2007HY2]
Step 3
-- Partition Function
CREATE PARTITION FUNCTION OrderDateRangePFN_HY (datetime)
AS
RANGE LEFT FOR VALUES ('20070630 23:59:59:997',
'20071231 23:59:59:997')

Step 4
-- Partition Scheme
CREATE PARTITION SCHEME OrderDatePScheme_HY
AS
PARTITION OrderDateRangePFN_HY
TO ([2007HY1], [2007HY2], [PRIMARY])

Step 5
-- Create Partitioned Table
CREATE TABLE OrderRange_HY
(
OrderID int NOT NULL,
OrderDate datetime NOT NULL
)
ON OrderDatePScheme_HY (OrderDate)
GO

-- Converting Unpartitioned table to Partitioned Table
CREATE INDEX OrderPart_INX
ON OrderRange_HY_Existing (OrderDate) -- this is an existing table
ON OrderDatePScheme_HY (OrderDate)
GO

Using Partitions in a Microsoft SQL Server 2000 Data Warehouse: http://msdn.microsoft.com/en-us/library/aa902650(SQL.80).aspx

MSDN: U.S. Local Highlights