Copyright (c) 2007 Mike Chirico (mchirico@gmail.com)
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation.
Last Updated: Fri Dec 21 12:37:14 EST 2007
TIP 1:
Need to know how much fragmentation?
DBCC SHOWCONTIG (tbl_transaction)
There is also a more advanced option
DBCC SHOWCONTIG (tbl_transaction) WITH TABLERESULTS, ALL_LEVELS
There is also a defrag command
DBCC INDEXDEFRAG(Northwind,Customers,1)
TIP 2:
This is a cool feature:
IF object_id('OutputTest') IS NOT NULL
BEGIN
drop table OutputTest
END
CREATE TABLE OutputTest
(
ID int NOT NULL,
Description varchar(max) NOT NULL,
)
INSERT INTO OutputTest (ID, Description) VALUES (1, 'row 1')
INSERT INTO OutputTest (ID, Description) VALUES (2, 'row 2')
INSERT INTO OutputTest (ID, Description) VALUES (3, 'row 3')
DECLARE @DeleteLog AS TABLE (LogID INT, LogEntry VARCHAR(MAX))
DELETE OutputTest
OUTPUT DELETED.ID, DELETED.Description INTO @DeleteLog
WHERE ID = 1
SELECT *into DeleteLog FROM @DeleteLog
select * from DeleteLog
TIP 3:
Standard table create statement, with getdate() for automatically
recording the time when a record was added.
CREATE TABLE [junk23](
[JunkID] [smallint] IDENTITY(1,1) NOT NULL,
[Name] varchar(20) NOT NULL,
[ModifiedDate] [datetime] NOT NULL DEFAULT (getdate()))
TIP 4:
create PROCEDURE Insert_Top as
/*
CREATE TABLE [dbo].[top](
[SPID] [float] NULL,
[Status] [nvarchar](255) NULL,
[Login] [nvarchar](255) NULL,
[HostName] [nvarchar](255) NULL,
[BlkBy] [nvarchar](255) NULL,
[DBName] [nvarchar](255) NULL,
[Command] [nvarchar](255) NULL,
[CPUTime] [float] NULL,
[DiskIO] [float] NULL,
[LastBatch] [nvarchar](255) NULL,
[ProgramName] [nvarchar](255) NULL,
[SPID1] [float] NULL,
[REQUESTID] [float] NULL,
[ModifiedDate] [datetime] NULL CONSTRAINT [DF_top_ModifiedDate] DEFAULT (getdate())
) ON [PRIMARY]
*/
INSERT INTO [DPart_P008_Dev].[dbo].[top]
(
[SPID],
[Status],
[Login],
[HostName],
[BlkBy],
[DBName],
[Command],
[CPUTime],
[DiskIO],
[LastBatch],
[ProgramName],
[SPID1],
[REQUESTID])
EXEC sp_who2
Now, create the loop procedure:
create PROCEDURE Loop_Insert_Top as
WHILE (1=1) BEGIN
EXEC insert_top
WAITFOR DELAY '00:01:00';
END
To view the records:
select * from [top]
TIP 5:
sp_help
sp_helptext Insert_Page7_into_Combined_sproc
"All that really happens when you create a procedure is that its
syntax is checked and its source code is inserted into the
syscomments system table"
TIP 6:
Getting a directory listing of the c:\ drive.
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
EXEC master..xp_cmdshell "dir c:\*"
TIP 7:
select
'Name' = o.name,
'Owner' = user_name(ObjectProperty( object_id, 'ownerid')),
'Object_type' = substring(v.name,5,31)
--into t_sp_help
from sys.all_objects o, master.dbo.spt_values v
where o.type = substring(v.name,1,2) collate database_default and v.type = 'O9T'
and substring(v.name,5,31) ='stored procedure'
and user_name(ObjectProperty( object_id, 'ownerid'))='dbo'
order by [Owner] asc, Object_type desc, Name asc
TIP 8:
You may need indexes. Try running the following query to see if the
value is above 5000.
SELECT *
FROM
(SELECT user_seeks * avg_total_user_cost * (avg_user_impact * 0.01) AS index_advantage,
migs.* FROM sys.dm_db_missing_index_group_stats migs) AS migs_adv
INNER JOIN sys.dm_db_missing_index_groups AS mig ON migs_adv.group_handle =
mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle
ORDER BY migs_adv.index_advantage
TIP 9:
Need to see what users are doing?
select * from sys.dm_exec_sessions
TIP 10:
Need the last day of the month?
Select
dateadd(mm,1,convert(datetime,convert(char(10),getdate(),110)) -
day(getdate())+1)-1
TIP 11:
Put last day of month into a user defined function.
create FUNCTION dbo.GetLastDayOfMonth()
RETURNS datetime
AS
BEGIN
DECLARE @OutDate datetime
set @OutDate = (Select dateadd(mm,1,convert(datetime,convert(char(10),getdate(),110))
- day(getdate())+1)-1)
RETURN(@OutDate)
END
Now call it:
select dbo.GetLastDayOfMonth()
TIP 12:
Need a function that gets the date a year ago at the beginning of
the month?
create FUNCTION dbo.Get1YearAgo()
RETURNS datetime
AS
BEGIN
DECLARE @OutDate datetime
set @OutDate = (Select dateadd(mm,-12,convert(datetime,convert(char(10),
getdate(),110)) - day(getdate())+1)
)
RETURN(@OutDate)
END
select dbo.Get1YearAgo()
TIP 13:
Need to get a list of all stored procedures?
SELECT name
FROM dbo.sysobjects
WHERE type = 'P' AND category = 0
TIP 14:
Need to get the median? Also see TIP 15 below and TIP 19.
SELECT Median=AVG(c1) FROM (
SELECT MIN(c1) AS c1 FROM (
SELECT TOP 50 PERCENT col AS c1 FROM table
ORDER BY c1 DESC) t
UNION ALL
SELECT MAX(c1) FROM (
SELECT TOP 50 PERCENT col AS c1 FROM table
ORDER BY c1) t
) M
(Also reference: http://www.sqlmag.com/Article/ArticleID/49827/49827.html)
But note, you can probably use the sp_executesql statement as well.
Here's a way to get the 75%.
WITH T AS
(
SELECT [Sls Rep],[Prod No],[UOM],[Unit Sales $],
ROW_NUMBER() OVER(PARTITION BY [Sls Rep],[Prod No],[UOM]
ORDER BY [Unit Sales $]) AS RowNum,
COUNT(*) OVER(PARTITION BY [Sls Rep],[Prod No],[UOM]) AS Cnt
FROM Pg7_all_trans
)
SELECT [Sls Rep],[Prod No],[UOM],Avg([Unit Sales $]) [Median Unit Sales $],
Max(RowNum) [RowNum], Max(Cnt) [Cnt] into Pg7_75
FROM T
WHERE RowNum >= 0.75*(Cnt+1) and RowNum <= 0.75*(Cnt+2)
GROUP BY [Sls Rep],[Prod No],[UOM]
TIP 15:
sp_executesql -- Executing the contents of a string as a SQL statement.
Declare @S nvarchar(500);
set @S = 'select * from' + ' junk'
execute sp_executesql @S
But wait! You can do this in a sproc:
create proc select_table(@a as nvarchar(50))
as
Declare @t as nvarchar(500);
set @t = 'select * from ' + @a;
execute sp_executesql @t
Now just run this as follows:
select_table 'junk';
Here's another example with parameters:
EXECUTE sp_executesql
N'SELECT * FROM AdventureWorks.HumanResources.Employee
WHERE ManagerID = @level',
N'@level tinyint',
@level = 109;
Here's an example with quotes:
Declare @S nvarchar(max);
set @S = '
IF object_id(''junk'') IS NOT NULL
BEGIN
DROP TABLE junk
END
create table
junk (a int,
b varchar(20));
insert into junk (a,b) values (1,''one'');
insert into junk (a,b) values (2,''two'');
select * from junk;
'
-- print @S
execute sp_executesql @S
(Also reference: http://msdn2.microsoft.com/en-us/library/ms188001.aspx)
TIP 16:
More sp_executesql --
DECLARE @sql AS NVARCHAR(MAX), @i AS INT;
SET @sql = N'';
SET @i = 1;
WHILE @i <= 100
BEGIN
SET @sql = @sql + N'PRINT ' + CAST(@i AS NVARCHAR(10))
+ NCHAR(13) + NCHAR(10);
SET @i = @i + 1;
END
EXEC sp_executesql @sql;
TIP 17:
Simple example of a union statement:
select * into t1_t2_combined from
(select * from t1
union
select * from t2) as a
TIP 18:
Need to find SQL version?
SELECT @@VERSION
or
SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'),
SERVERPROPERTY ('edition')
Reference:
http://support.microsoft.com/kb/321185
TIP 19:
Example calculating Median on the table Median_table
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter FUNCTION [dbo].[calc_median_product_uom] (@product as nvarchar(30),
@uom as nvarchar(4)
)
-- Created: Mike Chirico <mchirico@gmail.com>
-- Updated: Thu Sep 27 16:30:20 EDT 2007
--
-- Example Usage:
--
-- select product,uom,DPart_P008.dbo.calc_median_product_uom(product,uom) Median from Median_table
--
--
RETURNS money
AS
BEGIN
DECLARE @Median as money
SELECT @Median=AVG(c1) FROM (
SELECT MIN(c1) AS c1
FROM (SELECT TOP 50 PERCENT AvqPrice AS c1 FROM Median_table
where product=@product and uom=@uom ORDER BY c1 DESC
) as t
UNION ALL
select max(c1) as c1 from (
SELECT TOP 50 PERCENT AvqPrice AS c1 FROM
Median_table where product=@product and uom=@uom ORDER BY c1
) as t
) M
RETURN(@Median)
END
TIP 20:
Example listing all the indexes on table mytable.
select a.name table_name,
b.name index_name,
d.name column_name,
c.index_column_id
from sys.tables a,
sys.indexes b,
sys.index_columns c,
sys.columns d
where a.object_id = b.object_id
and b.object_id = c.object_id
and b.index_id = c.index_id
and c.object_id = d.object_id
and c.column_id = d.column_id
and a.name = 'mytable'
TIP 21:
Need a comparison between Oracle 10g and SQL 2005? Take a look at
the following:
http://www.wisdomforce.com/dweb/resources/docs/MSSQL2005_ORACLE10g_compare.pdf
TIP 22:
Need to free up space? The following query shows how much space
can be freed.
SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB
FROM sys.database_files;
To free up space from the database 'mydatabase' use the following
command:
DBCC SHRINKDATABASE('mydatabase',0);
To free up sapce from the logfile 'mylogfile' use the following command:
DBCC SHRINKFILE('mylogfile',0);
TIP 23:
Getting the Sum, Max across rows in a table.
Assume a simple table defined as follows:
create table junk
(a int,
b int,
c int);
insert into junk (a,b,c) values (1,4,3);
insert into junk (a,b,c) values (2,5,9);
insert into junk (a,b,c) values (3,8,2);
select *, (select sum(my_columns)
from (select a as my_columns
union all
select b
union all
select c) as t) as sum_column
from junk
Tip 24:
Delete all tables with the name delete in them.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Mike Chirico mchirico@gmail.com>
-- Create date: <Thu Nov 1 08:34:41 EDT 2007>
-- Description: <This proc will go through and delete
-- all tables with the name delete in them.>
-- =============================================
alter PROCEDURE free_space
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE cursor_value CURSOR
FOR
select name from sys.tables where name like '%delete%'
FOR READ ONLY
DECLARE @cursor_row_value varchar(120)
DECLARE @S nvarchar(500);
OPEN cursor_value
FETCH cursor_value INTO @cursor_row_value
WHILE (@@FETCH_STATUS=0) BEGIN
set @S = 'drop table ['+@cursor_row_value+']'
execute sp_executesql @S
FETCH cursor_value INTO @cursor_row_value
END
CLOSE cursor_value
DEALLOCATE cursor_value
END
GO
TIP 25:
What is the difference between UNION and UNION ALL? UNION only returns the distinct
number of rows and is slower than UNION ALL.
TIP 26:
What is the difference between NVARCHAR, VARCHAR and CHAR?
NVARCHAR takes two bytes, VARCHAR takes 1 byte, and CHAR is fixed
length.
TIP 27:
Order can make a difference when doing updates
IF object_id('tempdb..#t1') IS NOT NULL
BEGIN
DROP TABLE #t1
END
IF object_id('tempdb..#t2') IS NOT NULL
BEGIN
DROP TABLE #t2
END
IF object_id('tempdb..#t3') IS NOT NULL
BEGIN
DROP TABLE #t3
END
create table #t1 (a int, b int);
insert into #t1 (a,b) values (1,2);
insert into #t1 (a,b) values (1,5);
create table #t2 (a int ,b int, c int, d int, [order] int);
insert into #t2 (a,b,c,d,[order]) values (1,2,10,10,0);
insert into #t2 (a,b,c,d,[order]) values (1,2,50,60,1);
-- Change order here:
--select * into #t3 from #t2 order by [order] desc
select * into #t3 from #t2 order by [order] asc
update #t1
set #t1.a=#t3.c, #t1.b=#t3.d
from #t1 ,#t3
where #t1.a=#t3.a and #t1.b=#t3.b
select * from #t1
TIP 28:
Need a listing of all stored procedures on the system that you
created?
SELECT * -- Stored Procs
FROM sys.objects
WHERE objectproperty( object_id, N'IsMSShipped' ) = 0
AND objectproperty( object_id, N'IsProcedure' ) = 1
Below are some other common methods. But take a look at the
following below and note the condition where N'IsMSShipped' is
false, or equal to zero.
SELECT * -- Functions
FROM sys.objects
WHERE objectproperty( object_id, N'IsMSShipped' ) = 0
AND ( objectproperty( object_id, N'IsTableFunction' ) = 1
OR objectproperty( object_id, N'IsScalarFunction' ) = 1 )
SELECT * -- User tables
FROM sys.objects
WHERE objectproperty( object_id, N'IsMSShipped' ) = 0
AND objectproperty( object_id, N'IsTable' ) = 1
SELECT * -- Views
FROM sys.objects
WHERE objectproperty( object_id, N'IsMSShipped' ) = 0
AND objectproperty( object_id, N'IsView' ) = 1
Reference:
http://msdn2.microsoft.com/en-us/library/ms176105.aspx
http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/29/850.aspx
TIP 29:
Combining two tables into 1 pivot table
create table p1 (a int, b int)
create table p2 (a int, b int)
delete from p1;
delete from p2;
insert into p1 (a,b) values (1,34);
insert into p1 (a,b) values (2,12);
insert into p1 (a,b) values (3,22);
insert into p2 (a,b) values (1,500);
insert into p2 (a,b) values (2,512);
insert into p2 (a,b) values (4,600);
select g.a,g.b,g.c
from
(
select p1.a, p1.b,p2.b as c from p1, p2
where p1.a=p2.a
union all
select p1.a,p1.b,null as c from p1 left outer join
p2 on p1.a=p2.a
where p2.a is null
union all
select p2.a,null as b,p2.b as c from p2 left outer join
p1 on p2.a=p1.a
where p1.a is null
) as g
/* Results:
a b c
1 34 500
2 12 512
3 22 NULL
4 NULL 600
*/
ADDITIONAL TUTORIALS
Linux Quota Tutorial This tutorial walks you through implementing disk quotas for both users and groups on Linux, using a virtual filesystem, which is a filesystem created from a disk file. Since quotas work on a per-filesystem basis, this is a way to implement quotas on a sub-section, or even multiple subsections of your drive, without reformatting. This tutorial also covers quotactl, or quota's C interface, by way of an example program that can store disk usage in a SQLite database for monitoring data usage over time.Gmail on Home Linux Box using Postfix and Fetchmail If you have a Google Gmail account, you can relay mail from your home linux system. It's a good exercise in configuring Postfix with TLS and SASL. Plus, you will learn how to bring down the mail safely, using fetchmail with the "sslcertck" option.
Breaking Firewalls with OpenSSH and PuTTY If the system administrator deliberately filters out all traffic except port 22 (ssh), to a single server, it is very likely that you can still gain access other computers behind the firewall. This article shows how remote Linux and Windows users can gain access to firewalled samba, mail, and http servers. In essence, it shows how openSSH and Putty can be used as a VPN solution for your home or workplace.
Create your own custom Live Linux CD These steps will show you how to create a functioning Linux system, with the latest 2.6 kernel compiled from source, and how to integrate the BusyBox utilities including the installation of DHCP. Plus, how to compile in the OpenSSH package on this CD based system. On system boot-up a filesystem will be created and the contents from the CD will be uncompressed and completely loaded into RAM -- the CD could be removed at this point for boot-up on a second computer. The remaining functioning system will have full ssh capabilities. You can take over any PC assuming, of course, you have configured the kernel with the appropriate drivers and the PC can boot from a CD.
SQLite Tutorial This article explores the power and simplicity of sqlite3, first by starting with common commands and triggers, then the attach statement with the union operation is introduced in a way that allows multiple tables, in separate databases, to be combined as one virtual table, without the overhead of copying or moving data. Next, the simple sign function and the amazingly powerful trick of using this function in SQL select statements to solve complex queries with a single pass through the data is demonstrated, after making a brief mathematical case for how the sign function defines the absolute value and IF conditions.
Lemon Parser Tutorial Lemon is a compact, thread safe, well-tested parser generator written by D. Richard Hipp. Using a parser generator, along with a scanner like flex, can be advantageous because there is less code to write. You just write the grammar for the parser. This article is an introduction to the Lemon Parser, complete with examples.
Mike Chirico, a father of triplets (all girls) lives outside of
Philadelphia, PA, USA. He has worked with Linux since 1996, has a Masters
in Computer Science and Mathematics from Villanova University, and has
worked in computer-related jobs from Wall Street to the University of
Pennsylvania. His hero is Paul Erdos, a brilliant number theorist who was
known for his open collaboration with others.
Mike's notes page is souptonuts. For
open source consulting needs, please send an email to
mchirico@gmail.com. All consulting work must include a donation to
SourceForge.net.