Wednesday, 25 May 2011

How to Share Data Between Stored Procedures

How to Share Data Between Stored Procedures

  • Using OUTPUT Parameters
  • Table-valued User-defined Functions
  • Using a Table
  • Insert-Exec
  • Table Parameters, and Table Types
  • Using the CLR
  • Using XML
  • Using Cursor Variables

    A must read.
  • SELECT @@spid

    SELECT @@spid

    Using @@SPID to return the SessionID of the T-SQL session that the statements are currently in.

    HTML PRE Tag

    Definition and Usage

    The PRE tag defines preformatted text.

    Text in a PRE element is displayed in a fixed-width font (usually Courier), and it preserves both spaces and line breaks.

    Monday, 23 May 2011

    Using CROSS APPLY (t-sql)

    Using CROSS APPLY (t-sql)

    CREATE FUNCTION dbo.fn_GetTopOrders(@custid AS int, @n AS INT)
    SELECT TOP(@n) *
    FROM Sales.SalesOrderHeader
    WHERE CustomerID = @custid
    ORDER BY TotalDue DESC

    which returns the top n orders per customerID

    SELECT C.CustomerID,
    AdventureWorks.Sales.Customer AS C
    AdventureWorks.dbo.fn_GetTopOrders(C.CustomerID, 3) AS O
    CustomerID ASC, TotalDue DESC

    results in this...

    CustomerID SalesOrderID TotalDue
    ----------- ------------ ---------------------
    1 45283 37643.1378
    1 46042 34722.9906
    1 44501 26128.8674
    2 46976 10184.0774
    2 47997 5469.5941
    2 57044 4537.8484
    3 53616 92196.9738
    3 47439 78578.9054
    3 48378 56574.3871
    4 47658 132199.8023
    . . .

    The APPLY clause acts like a JOIN without the ON clause comes in two flavors: CROSS and OUTER.
    The OUTER APPLY clause returns all the rows on the left side (Customers)
    whether they return any rows in the table-valued-function or not (the "LEFT JOIN" table).

    The columns that the table-valued-function returns are null if no rows are returned.

    The CROSS APPLY only returns rows from the left side (Customers)
    if the table-valued-function returns rows.

    Notice that I'm just passing in the CustomerID to the function.
    It returns the TOP 3 rows based on the amount of the order.

    Since I'm using CROSS APPLY a customer without orders won't appear in the list.
    I can also pass in a number other than 3 to easily return a different number of orders per customer.

    Even better I can pass in a different number of orders for each customer.
    So I could list the top 5 orders for one type of customer but the top 10 for another type of customer.

    How cool is that?!?

    And it gets even better.
    Remember the function has an ORDER BY in it.
    It will always return the top orders based on the amount.
    However you can change the ORDER BY clause in the query that calls the function to display those rows in whatever order you want.
    You could easily display the top 3 orders in ascending order instead.

    [SQL] @@Identity, SCOPE_IDENTITY

    [SQL] @@Identity, SCOPE_IDENTITY()
    msdn link

    SCOPE_IDENTITY, IDENT_CURRENT, and @@IDENTITY are similar functions because they return values that are inserted into identity columns.

    IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the value generated for a specific table in any session and any scope. For more information, see IDENT_CURRENT (Transact-SQL).

    SCOPE_IDENTITY and @@IDENTITY return the last identity values that are generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.

    For example, there are two tables, T1 and T2, and an INSERT trigger is defined on T1. When a row is inserted to T1, the trigger fires and inserts a row in T2. This scenario illustrates two scopes: the insert on T1, and the insert on T2 by the trigger.

    Assuming that both T1 and T2 have identity columns, @@IDENTITY and SCOPE_IDENTITY will return different values at the end of an INSERT statement on T1. @@IDENTITY will return the last identity column value inserted across any scope in the current session. This is the value inserted in T2. SCOPE_IDENTITY() will return the IDENTITY value inserted in T1. This was the last insert that occurred in the same scope. The SCOPE_IDENTITY() function will return the null value if the function is invoked before any INSERT statements into an identity column occur in the scope.

    Failed statements and transactions can change the current identity for a table and create gaps in the identity column values. The identity value is never rolled back even though the transaction that tried to insert the value into the table is not committed. For example, if an INSERT statement fails because of an IGNORE_DUP_KEY violation, the current identity value for the table is still incremented.

    Thursday, 19 May 2011

    SQL Server Logins and Users

    Gleamed from

    SQL Server Logins and Users
    Although the terms login and user are often used interchangeably, they are very different.
  • A login is used for user authentication
  • A database user account is used for database access and permissions validation.

    Logins are associated to users by the security identifier (SID).
    A login is required for access to the SQL Server server. The process of verifying that a particular login is valid is called "authentication". This login must be associated to a SQL Server database user. You use the user account to control activities performed in the database. If no user account exists in a database for a specific login, the user that is using that login cannot access the database even though the user may be able to connect to SQL Server. The single exception to this situation is when the database contains the "guest" user account. A login that does not have an associated user account is mapped to the guest user. Conversely, if a database user exists but there is no login associated, the user is not able to log into SQL Server server.

    When a database is restored to a different server it contains a set of users and permissions but there may not be any corresponding logins or the logins may not be associated with the same users. This condition is known as having "orphaned users."

    Troubleshooting Orphaned Users
    When you restore a database backup to another server, you may experience a problem with orphaned users. The following scenario illustrates the problem and shows how to resolve it.
    Use master
    sp_addlogin 'test', 'password', 'Northwind'

    SELECT sid FROM dbo.sysxlogins WHERE name = 'test'

    Grant access to the user you just created
    Use Northwind
    sp_grantdbaccess 'test'
    SELECT sid FROM dbo.sysusers WHERE name = 'test'


    As you can see, both SID's are identical.

    Backup the database
    Use master
    TO DISK = 'C:\Northwind.bak'

    Copy the Backupfile to another Maschine and SQL Server and restore it as follows:
    FROM DISK = 'C:\Users\Zahn\Work\Northwind.bak'


    FROM DISK = 'C:\Users\Zahn\Work\Northwind.bak'
     MOVE 'Northwind' TO 'D:\DataMSSQL\Data\northwnd.mdf',
     MOVE 'Northwind_log' TO 'D:\DataMSSQL\Data\northwnd.ldf'

    The restored database contains a user named "test" without a corresponding login, which results in "test" being orphaned.

    Check the SID's
    Use master
    SELECT sid FROM dbo.sysxlogins WHERE name = 'test'


    Use TestDB
    SELECT sid FROM dbo.sysusers WHERE name ='test'


    Now, to detect orphaned users, run this code
    Use TestDB
    sp_change_users_login 'report'

    test 0xE5EFF2DB1688C246855B013148882E75

    The output lists all the logins, which have a mismatch between the entries in the sysusers system table, of the TestDB database, and the sysxlogins system table in the master database.

    Resolve Orphaned Users

    Use TestDB
    sp_change_users_login 'update_one', 'test', 'test'

    SELECT sid FROM dbo.sysusers WHERE name = 'test'

    use master
    SELECT sid FROM dbo.sysxlogins WHERE name ='test'


    This relinks the server login "test" with the the TestDB database user "test".
    The sp_change_users_login stored procedure can also perform an update of all orphaned users with the "auto_fix" parameter but this is not recommended because SQL Server attempts to match logins and users by name.
    For most cases this works; however, if the wrong login is associated with a user, a user may have incorrect permissions.

    Gleamed from MSDN library


    SQL Server 2000 Controls the default transaction locking behavior for all Microsoft® SQL Server™ SELECT statements issued by a connection.


    Specifies that shared locks are held while the data is being read to avoid dirty reads, but the data can be changed before the end of the transaction, resulting in nonrepeatable reads or phantom data. This option is the SQL Server default.

    Implements dirty read, or isolation level 0 locking, which means that no shared locks are issued and no exclusive locks are honored. When this option is set, it is possible to read uncommitted or dirty data; values in the data can be changed and rows can appear or disappear in the data set before the end of the transaction. This option has the same effect as setting NOLOCK on all tables in all SELECT statements in a transaction. This is the least restrictive of the four isolation levels.

    Locks are placed on all data that is used in a query, preventing other users from updating the data, but new phantom rows can be inserted into the data set by another user and are included in later reads in the current transaction. Because concurrency is lower than the default isolation level, use this option only when necessary.

    Places a range lock on the data set, preventing other users from updating or inserting rows into the data set until the transaction is complete. This is the most restrictive of the four isolation levels. Because concurrency is lower, use this option only when necessary. This option has the same effect as setting HOLDLOCK on all tables in all SELECT statements in a transaction.

    Only one of the options can be set at a time, and it remains set for that connection until it is explicitly changed. This becomes the default behavior unless an optimization option is specified at the table level in the FROM clause of the statement.

    The setting of SET TRANSACTION ISOLATION LEVEL is set at execute or run time and not at parse time.

    This example sets the TRANSACTION ISOLATION LEVEL for the session. For each Transact-SQL statement that follows, SQL Server holds all of the shared locks until the end of the transaction.

    SELECT * FROM publishers
    SELECT * FROM authors