Tuesday, December 02, 2008

Extra blank page when Save to PDF from SQL Reporting Service

When you save a report as PDF from Sql Reporting Services, you might see an extra blank page in between the pages in the report. This is due to the actual print out size exceed the page size that is specified.

For example, you specify your report size to be width (11 in) x height (8.5 in) which is a A4 size. However in the body of the report, you might have specify (intentionally or unintentionally) the size to be larger than that. When you save the report to PDF, you will see a blank page because the report size actually run over the page size.

To solve this problem, make sure you check the Size and Margin property of both the Report and Body (you can access this from the properties window).

Labels: , ,

Saturday, August 02, 2008

DataBoy v1.0.6.2 is Out!

DataBoy v1.0.6.2 is released!

New features include:

  • Ctrl + Shift + (Left/Right cursor) short cut key to switch between Result and Message tab.
  • Connection time out setting for SQL Server connection.
  • Open and Save connection as Connection Group to a file.
  • Remember last session.
  • Option to persist login info. Select Persist Login Info if you want database user name and password to be saved with the connection when you save a connection group.
  • Table column ordering in the data explorer panel tree view is now according to the sequence in the meta data.


You can download Databoy from Codeplex : Databoy

Labels: ,

Wednesday, July 23, 2008

Licensing Requirement to Install Reporting Service on separate server

I was asked if the SQL Server Reporting Service is installed in a separate server from where the SQL Server database engine is installed, does it need another SQL Server license?

Although I am not a licensing expert (and not many people seem to be able to understand Microsoft Licensing scheme), but I can confidently say Yes to the question above.

The answer lies in the following document:

Licensing Doc

In the above scenario, you need two SQL Server license.

I hope Microsoft can be more open and clear in communicating licensing issue and requirement in the future. It will be good if they can include some of the common deployment scenario for their software together with the licensing requirement in Technet.

Labels: , ,

Saturday, June 21, 2008

Planning for DataBoy vNext

I am currently planning and designing some new feature for the next version of DataBoy. I have receive some feedback for some enhancement that people would like to see.

This new release will be considered as minor update as there will be no new major feature that require significant design rework. All the new things are just enhancement that make DataBoy more usable.

Some of the enhancement that is planned includes:
- Short cut key to switch data and message tab.
- Connection time out in the Add Connection dialog (only for SQL Server).
- Set the cursor focus back to sql editor after a query is runned.
- Order column in data explorer tree view according to sequence in meta data.
- Persist database connection.

My target is to release in four weeks from now.

I would also like to re-iterate that the objective of DataBoy is to provide a simple tool to query database. It is not meant to be a database management tool. As such, all new feature request will be evaluated and design along this line.

The two main scenarios in which DataBoy is designed to support are:
a) Application support personnel/Developer can easily copy DataBoy into the end user computer (where there is no dev tool) or a computer where there is no SQl management tool installed and start querying the database for application diagnosis.

b) To enable application development with SQL CE much easier. At the time DataBoy was developed, the toolset for working with SQL CE v3.5 was very limited as SQL Server 2008 was not yet release and fully supported.


Having said that, I still welcome all feedbacks and enhancement request.

Labels:

Wednesday, April 09, 2008

DataBoy 1.0 released

I have just publish DataBoy version 1 in codeplex.


DataBoy is a small footprint and portable tool to perform simple query against SQL CE and SQL Server. It is used as an alternative query tool for SQL Management console.

The download link is here : DataBoy

Labels:

Sunday, September 18, 2005

TSQL date teaser. Bonus Question

Given a date, how do you tell which week in the month is that date?
EG : Given 1-Feb-2005, it is the 1st week in February.
Given 17-Feb-2005, it is the 3rd week in February.


declare @startOfMonth datetime
declare @myDate datetime
declare @weekOfYearForStartOfMonth int
declare @weekInMonth int

select @myDate = '17-feb-2005'
select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)
select @weekOfYearForStartOfMonth = datepart(ww, @startOfMonth)
select datepart(ww, @myDate) - @weekOfYearForStartOfMonth + 1

Labels:

Thursday, September 15, 2005

TSQL date teaser. Answer for Q6

6) A slight variation from (5), given a date, find the second Thursday
of the month.
E.G: Given 10-July-2005, second Thursday of the month is 14-July-2005.

Your solution must also be able to find (N)th (day of the week) of the month.
Where : N can be first week, second week and so on.
day of week can be any day from Sunday to Saturday.


declare @startOfNextMonth datetime
declare @endOfMonth datetime
declare @myDate varchar(20)
declare @DaysToAdd int
declare @NthWeek int
declare @TargetDayOfWeek int

select @myDate = '10-July-2005'

select @TargetDayOfWeek = 5
select @NthWeek = 2

select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)

select @DaysToAdd = (7 - ((datepart(dw,@startOfMonth) +
(7 - @TargetDayOfWeek)) % 7)) % 7

select dateadd(d, @DaysToAdd + ((@nthWeek-1)*7), @startOfMonth)

Labels:

TSQL date teaser. Answer for Q5

5). Given a date, find the first Tuesday of the month.
E.G: Given 10-July-2005, first Tuesday for the month is 5-July-2005.


declare @startOfNextMonth datetime
declare @endOfMonth datetime
declare @myDate varchar(20)
declare @DaysToAdd int
declare @TargetDayOfWeek int

select @myDate = '10-jul-2005'
select @TargetDayOfWeek = 3

select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)
print @startOfMonth

select @DaysToAdd = (7 - ((datepart(dw,@startOfMonth) +
(7 - @TargetDayOfWeek)) % 7)) % 7

select dateadd(d, @DaysToAdd, @startOfMonth)

Labels:

Wednesday, September 14, 2005

TSQL date teaser. Answer for Q4

4) A slight variation from (3), given a date, find the second last Thursday
of the month.
E.G: Given 10-July-2005, second last Thursday of the month is 21-July-2005.

Your solution must also be able to find (N)th last (day of the week) of the month.
Where : N can be last week, second last week, third last week and so on,
day of week can be any day from Sunday to Saturday.


declare @startOfNextMonth datetime
declare @endOfMonth datetime
declare @myDate varchar(20)
declare @DaysToMinus int
declare @NthWeek int
declare @TargetDayOfWeek int

select @myDate = '10-jul-2005'
select @NthWeek = 2
select @TargetDayOfWeek = 5

select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)
select @startOfNextMonth = dateadd(m, 1, @startOfMonth)
select @endOfMonth = dateadd(d, -1 , @startOfNextMonth)

select @DaysToMinus = ((datepart(dw,@endOfMonth) + (7-@TargetDayOfWeek)) % 7)
select dateadd(d, -(@DaysToMinus + ((@nthWeek-1)*7)), @endOfMonth)

Labels:

Tuesday, September 13, 2005

TSQL date teaser. Answer for Q3

3). Given a date, find the last Friday of the month.
E.G: Given 10-July-2005, last Friday for the month is 29-July-2005.


declare @startOfNextMonth datetime
declare @endOfMonth datetime
declare @myDate varchar(20)
declare @DaysToMinus int

select @myDate = '10-jul-2005'

select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)
print @startOfMonth

select @startOfNextMonth = dateadd(m, 1, @startOfMonth)
print @startOfNextMonth

select @endOfMonth = dateadd(d, -1 , @startOfNextMonth)
print @endOfMonth

select @DaysToMinus = -((datepart(dw,@endOfMonth) + 1) % 7)

select dateadd(d, @DaysToMinus, @endOfMonth)

Labels:

Monday, September 12, 2005

TSQL date teaser. Answer for Q2

2) Given a date, find the date of the first day and last day of the month.
E.G: Given 21-July-2005, You have to tell 1-July-2005 is the first day of
the month and 31-July-2005 is the last day of the month.


declare @startOfNextMonth datetime
declare @endOfMonth datetime
declare @myDate varchar(20)

select @myDate = '21-feb-2005'

select @startOfMonth = dateadd(d, (day(@myDate)-1)* -1, @myDate)
print @startOfMonth

select @startOfNextMonth = dateadd(m, 1, @startOfMonth)
print @startOfNextMonth

select @endOfMonth = dateadd(d, -1 , @startOfNextMonth)
print @endOfMonth

Labels:

Sunday, September 11, 2005

TSQL date teaser. Answer for Q1

This is a long outstanding post to my previous TSQL date teaser post.

1) Given a date, find the date of the first day and last day of that week.
E.G: Given 28-July-2005, You have to tell 24-July-2005 is the first day
of that week and 30-July-2005 is that last day of that week.


declare @dayOfWeek int
declare @startOfWeek datetime
declare @endOfWeek datetime
declare @myDate varchar(20)

select @myDate = '28-july-2005'
select @dayOfWeek = datepart(dw, @myDate)

select @startOfWeek = dateadd(d, (@dayOfWeek - 1)* -1, @myDate)
print @startOfWeek

select @endOfWeek = dateadd(d, 7 - @dayOfWeek , @myDate)
print @endOfWeek

Labels:

Friday, July 29, 2005

TSQL Date Teaser

Do you think you can solve the following problems using SQL Server TSQL ?

1) Given a date, find the date of the first day and last day of that week.
E.G: Given 28-July-2005, You have to tell 24-July-2005 is the first day
of that week and 30-July-2005 is that last day of that week.

2) Given a date, find the date of the first day and last day of the month.
E.G: Given 21-July-2005, You have to tell 1-July-2005 is the first day of
the month and 31-July-2005 is the last day of the month.

3). Given a date, find the last Friday of the month.
E.G: Given 10-July-2005, last Friday for the month is 29-July-2005.

4) A slight variation from (3), given a date, find the second last Thursday
of the month.
E.G: Given 10-July-2005, second last Thursday of the month is 21-July-2005.

Your solution must also be able to find (N)th last (day of the week) of the month.
Where : N can be last week, second last week, third last week and so on,
day of week can be any day from Sunday to Saturday.


5). Given a date, find the first Tuesday of the month.
E.G: Given 10-July-2005, first Tuesday for the month is 5-July-2005.

6) A slight variation from (5), given a date, find the second Thursday
of the month.
E.G: Given 10-July-2005, second Thursday of the month is 14-July-2005.

Your solution must also be able to find (N)th (day of the week) of the month.
Where : N can be first week, second week and so on.
day of week can be any day from Sunday to Saturday.

Condition :
1) You can only use TSQL Date and Time function.
2) Only simple expressions are allowed. (EG : add, minus, multiply, divide, assignment, variables).
3) Language element such as Loop, if..else, case statement are not allowed.
4) Assume first day of the week is Sunday and last day of the week is Saturday(which is default in most
SQL Server installation).
5) You can't deal with leap year explicitly. Meaning, you cannot write your own algorithm to check
for leap years. You are only allowed to use TSQL DateTime function.

Try it and I will post the solutions by the next 2 weeks.

Labels:

Sunday, May 22, 2005

Searching Hierarchical data in database : Part 2

In this part 2, I will perform the reverse of Step 1.
Given a employee, how do you find all his/her reporting managers (direct or indirectly) ?

Step 1 : Complete Part 1.

Step 2 : Create the following User-Defined Function:

CREATE FUNCTION fn_FindManagers (@InEmpId int)
RETURNS @retFindReports TABLE (emp_id int primary key,
emp_name varchar(50) NOT NULL,
mgrid int
)

/*Returns a result set that lists all the managers
who the given employee reports to directly or indirectly.*/
AS
BEGIN
DECLARE @RowsAdded int

-- table variable to hold accumulated results
DECLARE @Managers TABLE (emp_id int primary key,
emp_name varchar(50) NOT NULL,
mgrid int,
processed tinyint default 0)

-- initialize @Managers with direct manager of the given employee
INSERT @Managers
SELECT emp2.emp_id, emp2.emp_name, emp2.emp_mgr, 0
FROM employees, employees emp2
WHERE employees.emp_mgr=emp2.emp_id
AND employees.emp_id = @InEmpId
SET @RowsAdded = @@rowcount

-- While new manager were added in the previous iteration
WHILE @RowsAdded > 0
BEGIN
/*Mark all employee records whose manager are going
to be found in this iteration with processed=1.*/
UPDATE @Managers
SET processed = 1
WHERE processed = 0

-- Insert manager who manager the employees marked 1.
INSERT @Managers
SELECT emp2.emp_id, emp2.emp_name, emp2.emp_mgr, 0
FROM @Managers m, employees emp2
WHERE m.mgrid=emp2.emp_id
and emp2.emp_mgr <> emp2.emp_id and m.processed = 1
SET @RowsAdded = @@rowcount


/*Mark all employee records whose manager
have been found in this iteration.*/
UPDATE @Managers
SET processed = 2
WHERE processed = 1
END


if not exists(select * from @Managers m where m.emp_id in
(select emp_id from employees where emp_id=emp_mgr))
begin

INSERT @Managers
SELECT emp2.emp_id, emp2.emp_name, emp2.emp_mgr, 0
FROM employees emp2
WHERE emp2.emp_mgr = emp2.emp_id
AND exists (select * from @Managers m where m.mgrid=emp2.emp_id)

end

-- copy to the result of the function the required columns
INSERT @retFindReports
SELECT emp_id, emp_name, mgrid
FROM @Managers
RETURN
END



You are now good to go :
In your SQL Query Analyzer, run the following query :

select * from fn_FindManagers(19).

Substitude 19 with whatever Employee No you want to test.

Labels:

Searching Hierarchical data in database : Part 1

If your database has a table that keep track of employees and their reporting
manager, given an employee how can you can out all the employees who report
(direct or indirectly) to this particular employee ?

I will show you how to accomplish this using SQL Server 2000 User-Defined function.
This technique is applicable if you need to find hierarchical data stored in a table.

Step 1 : create the following Employees table :

CREATE TABLE [dbo].[Employees] (
[emp_id] [int] NOT NULL ,
[emp_name] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[emp_mgr] [int] NULL
) ON [PRIMARY]
GO


Step 2 : Insert the following data into the Employees table :

INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (1, 'ceo', 1)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (2, 'cio', 1)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (3, 'cfo', 1)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (4, 'coo', 1)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (5, 'app manager', 2)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (6, 'infra manager', 2)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (7, 'helpdesk manager', 2)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (8, 'purchasing manager', 3)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (9, 'account manager', 3)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (10, 'hr manager', 4)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (11, 'training manager', 4)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (12, 'sap engineer', 5)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (13, 'dev lead', 5)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (14, 'developer', 5)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (15, 'IIS admin', 6)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (16, 'AD admin', 6)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (17, 'Security Engineer', 6)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (18, 'Account Asst', 9)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (19, 'Purchasing Officer 1', 8)
INSERT INTO Employees(emp_id, emp_name, emp_mgr)
values (20, 'Purchasing Office 2', 8)



Step 3 : Create the following User-Defined Function:

CREATE FUNCTION fn_FindReports (@InEmpId int)
RETURNS @retFindReports TABLE (emp_id int primary key,
emp_name varchar(50) NOT NULL,
mgrid int
)

/*Returns a result set that lists all the
employees who report to given employee
directly or indirectly.*/
AS
BEGIN
DECLARE @RowsAdded int

-- table variable to hold accumulated results
DECLARE @reports TABLE (emp_id int primary key,
emp_name varchar(50) NOT NULL,
mgrid int,
processed tinyint default 0)

-- initialize @Reports with direct reports
-- of the given employee
INSERT @reports
SELECT emp_id, emp_name, emp_mgr, 0
FROM employees
WHERE emp_id = @InEmpId
SET @RowsAdded = @@rowcount

-- While new employees were added in the previous iteration
WHILE @RowsAdded > 0
BEGIN
/*Mark all employee records whose
direct reports are going to be found
in this iteration with processed=1.*/
UPDATE @reports
SET processed = 1
WHERE processed = 0

-- Insert employees who report to employees marked 1.
INSERT @reports
SELECT e.emp_id, e.emp_name, e.emp_mgr, 0
FROM employees e, @reports r
WHERE e.emp_mgr=r.emp_id
and e.emp_mgr <> e.emp_id
and r.processed = 1
SET @RowsAdded = @@rowcount

/*Mark all employee records
whose direct reports have
been found in this iteration.*/
UPDATE @reports
SET processed = 2
WHERE processed = 1
END

-- copy to the result of the
-- function the required columns
INSERT @retFindReports
SELECT emp_id, emp_name, mgrid
FROM @reports

RETURN
END




You are now good to go :
In your SQL Query Analyzer, run the following query :

select * from fn_FindReports(3).

Substitude 3 with whatever Employee No you want to test.

Labels:

Friday, October 01, 2004

SQL Server Identity column

The value of a identity column is always increased even after you remove all records in that table. Here are some tips how you can manipulate the seed value for identity column.

To remove all record in the table and reset the seed to its initial value, run :
TRUNCATE TABLE YourTableName

To find out seed info about the identity column, run :
DBCC CHECKIDENT (YourTableName, NORESEED)

To set the seed value to a particular value (Eg: The seed value is currently 25, so the next value to be insert into the column is 26, but you want to it to be 31), run :
DBCC CHECKIDENT (YourTableName, RESEED, 30)

Note : If you specify the new seed valus to N, the next value to be insert will be N + 1.

Labels:

Truncate SQL Server Database Log

Over time, the database log file can grow very large. In those cases, you might want to truncate the log to free up spaces. Here is how you can do it.

-- Truncate the log. It DOES NOT backup the log!!!
backup log testdb WITH NO_LOG

-- Shrink the log file
dbcc shrinkfile(database_logfile, truncateonly)

You can find out the name of your database log file by running the following stored proc:
EXEC sp_helpfile

After you truncate the log, the changes to the data are not recoverable. Make sure you always backup your database after truncating the log.

Labels:

Tuesday, September 28, 2004

Retrieving SQL Server 2000 Property

Here is a function to retrieve SQL Server 2000's property such as edition, version, patch, license and etc.

select serverproperty('edition')
select serverproperty('ProductVersion')
select serverproperty('LicenseType')
select serverproperty('NumLicenses')
select serverproperty('ProductLevel')
select serverproperty('ServerName')

For more information, look for 'serverproperty' in SQL Server Book Online.

Labels:

Sunday, September 26, 2004

SQL Server 2005 Beta 2 Installation Error

If you are installing SQL Server 2005 beta 2 from the CD given out during Teched, you will encounter an error. The installer will complain it cannot find a particular file.

To workaround this, you need to copy the CD into your hard disk, rename the following 3 files and then run the setup form your hard disk.


1. Rename
\Setup\Program Files\Microsoft SQL Server\90\COM\Microsoft.SqlServer.Replication.NativeResourceStringLo.netmodule

To
\Setup\Program Files\Microsoft SQL Server\90\COM\Microsoft.SqlServer.Replication.NativeResourceStringLoader.netmodule

2. Rename
\Setup\Program Files\Microsoft SQL Server\90\Tools\Profiler\TraceDefinitions\1033\Microsoft Data Transformation Services TraceDescriptions 9.0.xml

To
\Setup\Program Files\Microsoft SQL Server\90\Tools\Profiler\TraceDefinitions\1033\Microsoft Data Transformation Services TraceDescriptions 9.0.0.xml

3. Rename
\Setup\Program Files\Microsoft SQL Server\90\SDK\Assemblies\Microsoft.SqlServer.Replication.NativeResourceStringLo.netmodule

To
\Setup\Program Files\Microsoft SQL Server\90\SDK\Assemblies\Microsoft.SqlServer.Replication.NativeResourceStringLoader.netmodule

Labels:

Wednesday, August 11, 2004

Preventing SQL Injection

I was reading the Database Input chapter on Writing Secure Code 2nd edition.

SQL injection is no longer a new thing. It has been mentioned many many times.

Some well known prevention technique includes :
DO NOT dynamically constuct SQL statement in your code.
Use Named Parameter on SQL.
Use QUOTE function to nullify invalid character in object names.
Use Stored Procedure.

Using stored procedure is an interesting topic to talk about. While it solve some problems, it does not solve all. If you are using an unsafe SQL in your stored procedure, you are defeating everything else.

Creating dynamic SQL in code is also very common scenerio. I do this very often in situation where the actual SQL is depends on user input. For example, in the search feature of my app, user can choose to filter/search by different fields. The actual SQL that is constructed will then depend on the user fields that he choose.

If you have to construct dynamic SQL, always use Named Parameter in the SQL. And if you are constructing the SQL in stored procedure, use the sp_executesql system stored procedure.

Labels: ,