-- 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_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
GO
-- Sample:
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
http://msdn.microsoft.com/en-us/library/ms175976.aspx
t-sql - Retrieving Error Information
t-sql find object references
select object_name(object_id), OBJECT_DEFINITION(object_id)
from sys.objects
where OBJECT_DEFINITION(object_id) like '%CDS%' and type='P'
örn: ProductId alanının kullanıldığı sp'ler.
Etiketler: t-sql
indexed view with schemabinding
ALTER VIEW [dbo].[Vw_View1] WITH SCHEMABINDING AS
SELECT ...
FROM ...
CREATE UNIQUE CLUSTERED INDEX [IX_Index1] ON [dbo].[Vw_View1]
(
[Column1] ASC
)
GO
related errors:
Cannot create index on view because the view is not schema bound.
http://www.mssqltips.com/tip.asp?tip=1610
basic t-sql commands
-- add primary key to a table
ALTER TABLE Karar ADD CONSTRAINT
PK_Karar PRIMARY KEY NONCLUSTERED
(
KararId
) ON [PRIMARY]
GO
-- change data type of a column
alter table Products
alter column ProductName varchar(250)
Etiketler: t-sql
t-sql: how to delete duplicate records
Method 1: SET ROWCOUNT
Syntax for SET ROWCOUNT is as follows:
SET ROWCOUNT { number | @number_var }
SET ROWCOUNT limits the sql server engine to process a specific number of rows. So the process stops after the defined number of rows are reached. The default value for ROWCOUNT is 0 which means no limit on the returning result set so all rows are returned. After a ROWCOUNT command is run and all processes are completed, you can also set the ROWCOUNT to 0 to turn off this option.
If we return back to our sample, in order to delete four times repeated rows, we can set the ROWCOUNT value to 3
SET ROWCOUNT 3
DELETE FROM Users WHERE FirstName = N'Elvis' AND LastName = N'Presley'
SET ROWCOUNT 0
-- (3 row(s) affected)
After running the above DELETE FROM command with SET ROWCOUNT statement, the last status of the table Users as below.
We are successfull to delete the identical rows with the row number 9 in the above picture.
If you want to delete the identical records automatically we can use a cursor. It is important that while you are declaring the cursor for dublicate rows, you should select the count of identical rows minus one, since we want one of the dublicated records exist in the table after delete processes.
You should also pay attention to the SET ROWCOUNT commands around the DELETE FROM command in the body of the cursor.
DECLARE @Count int
DECLARE @FirstName nvarchar(50)
DECLARE @LastName nvarchar(50)
DECLARE dublicate_cursor CURSOR FAST_FORWARD FOR
SELECT FirstName, LastName, Count(*) - 1
FROM Users
GROUP BY FirstName, LastName
HAVING Count(*) > 1
OPEN dublicate_cursor
FETCH NEXT FROM dublicate_cursor INTO @FirstName, @LastName, @Count
WHILE @@FETCH_STATUS = 0
BEGIN
SET ROWCOUNT @Count
DELETE FROM Users WHERE FirstName = @FirstName AND LastName = @LastName
SET ROWCOUNT 0
FETCH NEXT FROM dublicate_cursor INTO @FirstName, @LastName, @Count
END
CLOSE dublicate_cursor
DEALLOCATE dublicate_cursor
Method 2: TOP
A second method we can use while removing dublicate records from Users table is using the TOP expression in DELETE statement. With the release of SQL Server 2005, as an T-SQL enhancement TOP expression now takes a variable where else in SQL Server 2000 TOP was expecting a constant numeric value. This is very useful since if we decide to use a cursor, etc to delete all dublicates once, we may use a variable with the TOP expression.
If we return back to our original sample data in the Users table, we can run a similar command to remove two of the three identical records having firstname equal to Jane and last name equal to Fonda
DELETE TOP (2) FROM Users
WHERE FirstName = N'Jane' AND LastName = N'Fonda'
If you have not used the (n) syntax, you shoul get the following error; don't worry, just use the paranthesis.
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near '2'.
You can guess that we can use this DELETE TOP combination within a cursor in order to remove all the dublicated records leaving only one of them in the sample table. Here is the cursor that we can use:
DECLARE @Count int
DECLARE @FirstName nvarchar(50)
DECLARE @LastName nvarchar(50)
DECLARE dublicate_cursor CURSOR FAST_FORWARD FOR
SELECT FirstName, LastName, Count(*) - 1
FROM Users
GROUP BY FirstName, LastName
HAVING Count(*) > 1
OPEN dublicate_cursor
FETCH NEXT FROM dublicate_cursor INTO @FirstName, @LastName, @Count
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE TOP(@Count) FROM Users WHERE FirstName = @FirstName AND LastName = @LastName
FETCH NEXT FROM dublicate_cursor INTO @FirstName, @LastName, @Count
END
CLOSE dublicate_cursor
DEALLOCATE dublicate_cursor
Again I want to point to the issue that ROWCOUNT will not be considered in the next releases of SQL SERVER. You can find this information in the BOL on topics about ROWCOUNT and TOP. You can refer to ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.en/udb9/html/50705caa-4d0a-490f-92a4-75ece96e0a54.htm for more information. I also copied the important note from BOL to here:
Using SET ROWCOUNT will not affect DELETE, INSERT, and UPDATE statements in the next release of SQL Server. Avoid using SET ROWCOUNT with DELETE, INSERT, and UPDATE statements in new development work, and plan to modify applications that currently use it. We recommend that DELETE, INSERT, and UPDATE statements that currently are using SET ROWCOUNT be rewritten to useTOP.
Method 3: Adding an IDENTITY column
A third method can be adding an identity column to the table in order to distinguish all rows from each other. Of course, if you do not have the permissions to alter the table in order to add a new column, this method can not be implemented.
Run the below sql command to add a new column to the Users table, which will also fill the newly added column Id with integer values in sequential order and will distinguish each record from its identical ones.
ALTER TABLE Users ADD Id int IDENTITY(1,1)
After you run the above command, Users table will be as below:
Now it is easy to delete dublicates by using the Id column. For example, for dublicates of row with Id 8, we can run the below command
DELETE FROM Users WHERE Id IN (2,10,12)
And now let's look how we can automatically delete dublicates in this situation. We can use a Common Table Expression (CTE) to make a change and use a CTE instead of using a cursor. Here is the CTE (common table expression) sample that will delete the dublicates in our Users table.
WITH Dublicates_CTE(FirstName, LastName, Id)
AS
(
SELECT FirstName, LastName, Min(Id) Id
FROM Users
GROUP BY FirstName, LastName
HAVING Count(*) > 1
)
DELETE FROM Users
WHERE Id IN (
SELECT Users.Id
FROM Users
INNER JOIN Dublicates_CTE
ON Users.FirstName = Dublicates_CTE.FirstName
AND Users.LastName = Dublicates_CTE.LastName
AND Users.Id <> Dublicates_CTE.Id
)
It is important to note that CTEs (Common Table Expressions) are also new enhancements in t-sql with the new release of SQL Server, SQL Server 2005. So the above sql statement will not run on SQL Server 2000 databases. For more samples and definition on CTEs you can read the article titled Common Table Expression.
After you have done, you can drop the identity column Id by running an ALTER TABLE command as shown below:
ALTER TABLE Users DROP COLUMN Id
http://www.kodyaz.com/articles/delete-duplicate-records-rows-in-a-table.aspx
Etiketler: duplicate records , t-sql
Should I use a #temp table or a @table variable?
Should I use a #temp table or a @table variable?
There is a partial list of questions and answers about table variables, including some differences between table variables and #temp tables, in KB #305977 - INF: Frequently Asked Questions - SQL Server 2000 - Table Variables.
Local Temporary TablesCREATE TABLE #people
(
id INT,
name VARCHAR(32)
)
A temporary table is created and populated on disk, in the system database tempdb — with a session-specific identifier packed onto the name, to differentiate between similarly-named #temp tables created from other sessions. The data in this #temp table (in fact, the table itself) is visible only to the current scope (usually a stored procedure, or a set of nested stored procedures). The table gets cleared up automatically when the current procedure goes out of scope, but you should manually clean up the data when you're done with it:DROP TABLE #people
This will be better on resources ("release early") than if you let the system clean up *after* the current session finishes the rest of its work and goes out of scope.
A common use of #temp tables is to summarize/compact/reorganize data coming from another stored procedure. So, take this example, which pares down the results of the system procedure sp_who2 into only the SPID, Status, and HostName of *active* processes that are *not* part of the regular operation of the system:CREATE TABLE #sp_who3
(
SPID INT,
Status VARCHAR(32) NULL,
Login SYSNAME NULL,
HostName SYSNAME NULL,
BlkBy SYSNAME NULL,
DBName SYSNAME NULL,
Command VARCHAR(32) NULL,
CPUTime INT NULL,
DiskIO INT NULL,
LastBatch VARCHAR(14) NULL,
ProgramName VARCHAR(32) NULL,
SPID2 INT
)
INSERT #sp_who3 EXEC sp_who2 'active'
SELECT SPID, Status, HostName FROM #sp_who3
WHERE spid > 15
DROP TABLE #sp_who3
One of the main benefits of using a #temp table, as opposed to a permanent table, is the reduction in the amount of locking required (since the current user is the only user accessing the table), and also there is much less logging involved. (You could also increase this performance by placing tempdb on a separate drive... but that's another story.)
One minor problem with #temp tables is that, because of the session-specific identifier that is tacked onto the name, the name you give it is limited to 116 characters, including the # sign (while other table types are limited to 128). If you try, you will see this:Server: Msg 193, Level 15, State 1, Line 1
The object or column name starting with '#
Hopefully this won't be a limitation in your environment, because I can't imagine a table name that long being useful or manageable.
Another potential problem with #temp tables is that, if you enter a transaction and use a #temp table, and then cancel without ever issuing a ROLLBACK or COMMIT, you could be causing unnecessary locks in tempdb (for more information, see KB #159747).
Global Temporary TablesCREATE TABLE ##people
(
id INT,
name VARCHAR(32)
)
Global temporary tables operate much like local temporary tables; they are created in tempdb and cause less locking and logging than permanent tables. However, they are visible to all sessions, until the creating session goes out of scope (and the global ##temp table is no longer being referenced by other sessions). If two different sessions try the above code, if the first is still active, the second will receive the following:Server: Msg 2714, Level 16, State 6, Line 1
There is already an object named '##people' in the database.
I have yet to see a valid justification for the use of a global ##temp table. If the data needs to persist to multiple users, then it makes much more sense, at least to me, to use a permanent table. You can make a global ##temp table slightly more permanent by creating it in an autostart procedure, but I still fail to see how this is advantageous over a permanent table. With a permanent table, you can deny permissions; you cannot deny users from a global ##temp table.
Permanent TablesCREATE TABLE people
(
id INT,
name VARCHAR(32)
)
A permanent table is created in the local database, however you can (unlike #temp tables) choose to create a table in another database, or even on another server, for which you have access. Like global ##temp tables, a permanent table will persist the session in which it is created, unless you also explicitly drop the table. (For contention and concurrency reasons, creating a "temporary" permanent table in this manner doesn't really make a lot of sense.) If you are planning to create a permanent table when the procedure runs, you should check to see if it exists, in order to avoid errors like the one mentioned above. For more information about checking for the existence of both local #temp tables and permanent tables, see Article #2458.
Like global ##temp tables, there seems to be little reason to use a permanent table unless the data is going to persist... and if that is the case, why not create the permanent table before the stored procedure is ever run, thereby eliminating all the CREATE / DROP logic?
Table VariablesDECLARE @people TABLE
(
id INT,
name VARCHAR(32)
)
A table variable is created in memory, and so performs slightly better than #temp tables (also because there is even less locking and logging in a table variable). A table variable might still perform I/O to tempdb (which is where the performance issues of #temp tables make themselves apparent), though the documentation is not very explicit about this.
Table variables are automatically cleared when the procedure or function goes out of scope, so you don't have to remember to drop or clear the data (which can be a good thing or a bad thing; remember "release early"?). The tempdb transaction log is less impacted than with #temp tables; table variable log activity is truncated immediately, while #temp table log activity persists until the log hits a checkpoint, is manually truncated, or when the server restarts.
Table variables are the only way you can use DML statements (INSERT, UPDATE, DELETE) on temporary data within a user-defined function. You can create a table variable within a UDF, and modify the data using one of the above statements. For example, you could do this:CREATE FUNCTION dbo.example1
(
)
RETURNS INT
AS
BEGIN
DECLARE @t1 TABLE (i INT)
INSERT @t1 VALUES(1)
INSERT @t1 VALUES(2)
UPDATE @t1 SET i = i + 5
DELETE @t1 WHERE i < style="font-family: 'franklin gothic book', tahoma, verdana; font-size: 13px; ">
DECLARE @max INT
SELECT @max = MAX(i) FROM @t1
RETURN @max
END
GO
However, try that with a #temp table:CREATE FUNCTION dbo.example2
(
)
RETURNS INT
AS
BEGIN
CREATE TABLE #t1 (i INT)
INSERT #t1 VALUES(1)
INSERT #t1 VALUES(2)
UPDATE #t1 SET i = i + 5
DELETE #t1 WHERE i < style="font-family: 'franklin gothic book', tahoma, verdana; font-size: 13px; ">
DECLARE @max INT
SELECT @max = MAX(i) FROM #t1
RETURN @max
END
GO
Results:Server: Msg 2772, Level 16, State 1, Procedure example2, Line 7
Cannot access temporary tables from within a function.
Or try accessing a permanent table:CREATE TABLE table1
(
id INT IDENTITY,
name VARCHAR(32)
)
GO
CREATE FUNCTION dbo.example3
(
)
RETURNS INT
AS
BEGIN
INSERT table1(name) VALUES('aaron')
RETURN SCOPE_IDENTITY()
END
GO
Results:Server: Msg 443, Level 16, State 2, Procedure example3, Line 8
Invalid use of 'INSERT' within a function.
Table variables can lead to fewer stored procedure recompilations than temporary tables (see KB #243586 and KB #305977), and — since they cannot be rolled back — do not bother with the transaction log.
So, why not use table variables all the time? Well, when something sounds too good to be true, it probably is. Let's visit some of the limitations of table variables (part of this list was derived fromKB #305977):INSERT @table EXEC sp_someProcedure
SELECT * INTO @table FROM someTableDECLARE @myTable TABLE
(
CPK1 int,
CPK2 int,
CONSTRAINT myPK PRIMARY KEY (CPK1, CPK2)
)
-- yields:
Server: Msg 156, Level 15, State 1, Line 6
Incorrect syntax near the keyword 'CONSTRAINT'.
-- yet the following works:
DECLARE @myTable TABLE
(
CPK1 int,
CPK2 int,
PRIMARY KEY (CPK1, CPK2)
)SELECT * INTO @tableVariable
-- yields:
Server: Msg 170, Level 15, State 1, Line 1
Line 1: Incorrect syntax near '@tableVariable'.
You also can't build the table variable inside dynamic SQL, and expect to use it outside that scope, e.g.:DECLARE @colList VARCHAR(8000), @sql VARCHAR(8000)
SET @colList = 'a INT,b INT,c INT'
SET @sql = 'DECLARE @foo TABLE('+@colList+')'
EXEC(@sql)
INSERT @foo SELECT 1,2,3
-- this last line fails:
Server: Msg 137, Level 15, State 2, Line 5
Must declare the variable '@foo'.
This is because the rest of the script knows nothing about the temporary objects created within the dynamic SQL. Like other local variables, table variables declared inside of a dynamic SQL block (EXEC or sp_executeSQL) cannot be referenced from outside, and vice-versa. So you would have to write the whole set of statements to create and operate on the table variable, and perform it with a single call to EXEC or sp_executeSQL.CREATE TABLE #foo(id INT)
DECLARE @foo TABLE(id INT)
INSERT #foo VALUES(1)
INSERT #foo VALUES(2)
INSERT #foo VALUES(3)
INSERT @foo SELECT * FROM #foo
SELECT id
FROM @foo
INNER JOIN #foo
ON @foo.id = #foo.id
DROP TABLE #foo
The above fails with the following error:Server: Msg 137, Level 15, State 2, Line 11
Must declare the variable '@foo'.
This query, on the other hand, works fine:SELECT id
FROM @foo f
INNER JOIN #foo
ON f.id = #foo.idCREATE PROCEDURE faq_outer
AS
BEGIN
CREATE TABLE #outer
(
letter CHAR(1)
)
EXEC faq_inner
SELECT letter FROM #outer
DROP TABLE #outer
END
GO
CREATE PROCEDURE faq_inner
AS
BEGIN
INSERT #outer VALUES('a')
END
GO
EXEC faq_outer
Results:letter
------
a
(1 row(s) affected)
However, you cannot do this with table variables. The parser will find the error before you can even create it:CREATE PROCEDURE faq_outer
AS
BEGIN
DECLARE @outer TABLE
(
letter CHAR(1)
)
EXEC faq_inner
SELECT letter FROM @outer
END
GO
CREATE PROCEDURE faq_inner
AS
BEGIN
INSERT @outer VALUES('a')
END
GO
Results:Server: Msg 137, Level 15, State 2, Procedure faq_inner, Line 4
Must declare the variable '@outer'.
For more information about sharing data between stored procedures, please see this article by Erland Sommarskog.
Conclusion
Like many other areas of technology, there is no "right" answer here. For data that is not meant to persist beyond the scope of the procedure, you are typically choosing between #temp tables and table variables. Your ultimate decision should depend on performance and reasonable load testing. As your data size gets larger, and/or the repeated use of the temporary data increases, you will find that the use of #temp tables makes more sense. Depending on your environment, that threshold could be anywhere — however you will obviously need to use #temp tables if any of the above limitations represents a significant roadblock.
Etiketler: t-sql , table variable , temp table