<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Discrete Information</title>
	<atom:link href="http://www.discreteinformation.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.discreteinformation.com</link>
	<description>Providing a finite amount of information.</description>
	<lastBuildDate>Sun, 23 Aug 2009 03:42:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SQL Injection Attacks on the Rise</title>
		<link>http://www.discreteinformation.com/2009/08/sql-injection-attacks-on-the-rise/</link>
		<comments>http://www.discreteinformation.com/2009/08/sql-injection-attacks-on-the-rise/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 03:35:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Injection Attacks]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=79</guid>
		<description><![CDATA[According to a recent article at Dark Reading, SQL injection attacks are on the rise. Surprisingly it’s not due to a new technique, increasing success, or great ingenuity. Instead, it’s just old standby methods being used in great numbers due to simplicity and the possibility of valuable results.
Source:  Tech Insight: SQL Injection Demystified, Dark [...]]]></description>
			<content:encoded><![CDATA[<p>According to a recent article at <a href="http://www.darkreading.com">Dark Reading</a>, SQL injection attacks are on the rise. Surprisingly it’s not due to a new technique, increasing success, or great ingenuity. Instead, it’s just old standby methods being used in great numbers due to simplicity and the possibility of valuable results.</p>
<p>Source: <a href="http://www.darkreading.com/database_security/security/app-security/showArticle.jhtml?articleID=219401046"> Tech Insight: SQL Injection Demystified</a>, Dark Reading</p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/08/sql-injection-attacks-on-the-rise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ten Things to Help SQL Beginners</title>
		<link>http://www.discreteinformation.com/2009/06/ten-things-to-help-sql-beginner/</link>
		<comments>http://www.discreteinformation.com/2009/06/ten-things-to-help-sql-beginner/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 02:19:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Jet]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=71</guid>
		<description><![CDATA[In a recent post at TechRepublic, some beginner SQL tips were listed. They include definitions and examples for DISTINCT, GROUP BY, various aggregate functions, and other basic commands. The article focuses on Jet, but many tips apply to other SQL products too.
Source: 10+ tips for working smarter with SQL, TechRepublic
]]></description>
			<content:encoded><![CDATA[<p>In a recent post at <a href="http://www.techrepublic.com">TechRepublic</a>, some beginner SQL tips were listed. They include definitions and examples for <code>DISTINCT</code>, <code>GROUP BY</code>, various aggregate functions, and other basic commands. The article focuses on <code>Jet</code>, but many tips apply to other SQL products too.</p>
<p>Source: <a href="http://blogs.techrepublic.com.com/10things/?p=796">10+ tips for working smarter with SQL</a>, TechRepublic</p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/06/ten-things-to-help-sql-beginner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using OUTPUT with UPDATE</title>
		<link>http://www.discreteinformation.com/2009/06/using-output-with-update/</link>
		<comments>http://www.discreteinformation.com/2009/06/using-output-with-update/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 03:52:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[OUTPUT]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=62</guid>
		<description><![CDATA[As seen in earlier posts, a very useful clause in SQL Server 2005 and beyond is OUTPUT. Here is an example within an UPDATE statement.
Here&#8217;s our table structure:
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'users')
BEGIN
  DROP TABLE [users];
END;

CREATE TABLE [users] (
  [user_id] INT PRIMARY KEY IDENTITY(1,1),
  username VARCHAR(16),
  [password] [...]]]></description>
			<content:encoded><![CDATA[<p>As seen in earlier posts, a very useful clause in SQL Server 2005 and beyond is <code>OUTPUT</code>. Here is an example within an <code>UPDATE</code> statement.</p>
<p>Here&#8217;s our table structure:</p>
<pre>IF EXISTS (SELECT * FROM sys.tables WHERE name = 'users')
BEGIN
  DROP TABLE [users];
END;

CREATE TABLE [users] (
  [user_id] INT PRIMARY KEY IDENTITY(1,1),
  username VARCHAR(16),
  [password] VARCHAR(16),
  email VARCHAR(128)
);</pre>
<p>Here is a <code>changeUserName</code> procedure to update a user&#8217;s username, using an <code>OUTPUT</code> clause:</p>
<pre>
CREATE PROC changeUserName
  @user_ip varchar(15),
  @password varchar(16),
  @username_old varchar(16),
  @username_new varchar(16)
AS

  SET NOCOUNT ON;

  CREATE TABLE #updatedUser(
    user_id INT,
    username_old VARCHAR(16),
    username_new VARCHAR(16));

  UPDATE [users]
    SET [username] = @username_new
  OUTPUT DELETED.user_id, DELETED.username, INSERTED.username
    INTO #updatedUser(user_id, username_old, username_new)
  WHERE [users].username = @username_old
    AND CAST([users].[password] AS VARBINARY(16))
      = CAST(@password AS VARBINARY(16));

  SET NOCOUNT OFF;

  SELECT user_id, username_old, username_new
    FROM #updatedUser;

  DROP TABLE #updatedUser;
</pre>
<p>Here is an example of that procedure in action:</p>
<pre>
EXEC [addUser] @user_ip = '192.168.1.2',
  @username = 'john',
  @password = 'john!password',
  @email = 'john@yahoo.com';

user_id
-----------
1

EXEC [changeUserName]
  @user_ip = '192.168.1.1',
  @username_old = 'john',
  @username_new = 'john_new',
  @password='john!password';

user_id     old_username     new_username
------- ---------------- ----------------
1           john         john_new
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/06/using-output-with-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Good New, Faster Wireless Internet on Its Way</title>
		<link>http://www.discreteinformation.com/2009/05/faster-wireless-internet/</link>
		<comments>http://www.discreteinformation.com/2009/05/faster-wireless-internet/#comments</comments>
		<pubDate>Wed, 27 May 2009 22:45:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Wireless]]></category>
		<category><![CDATA[AT&T]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=57</guid>
		<description><![CDATA[Starting this year, with the intention to be complete by 2011 in most metropolitan areas, AT&#38;T plans to double their potential Internet access speed for wireless devices. This will increase the theoretical limit for a device on their network from 3 Mbps to over 7 Mbps.
Source: AT&#38;T says to double mobile data speeds by 2011, [...]]]></description>
			<content:encoded><![CDATA[<p>Starting this year, with the intention to be complete by 2011 in most metropolitan areas, AT&amp;T plans to double their potential Internet access speed for wireless devices. This will increase the theoretical limit for a device on their network from 3 Mbps to over 7 Mbps.</p>
<p>Source: <a href="http://www.reuters.com/article/internetNews/idUSTRE54Q4TS20090527">AT&amp;T says to double mobile data speeds by 2011</a>, Reuters</p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/05/faster-wireless-internet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t Forget the OUTPUT Clause</title>
		<link>http://www.discreteinformation.com/2009/05/dont-forget-the-output-clause/</link>
		<comments>http://www.discreteinformation.com/2009/05/dont-forget-the-output-clause/#comments</comments>
		<pubDate>Wed, 27 May 2009 01:22:21 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[OUTPUT]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=44</guid>
		<description><![CDATA[One of the more useful clauses available in SQL Server 2005 and beyond is OUTPUT, but it is rarely seen in use. Here is a quick example of how to use it within an INSERT statement.
Let&#8217;s setup our table structure first:
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'users')
BEGIN
  DROP TABLE [users];
END;

CREATE TABLE [users] [...]]]></description>
			<content:encoded><![CDATA[<p>One of the more useful clauses available in SQL Server 2005 and beyond is <code>OUTPUT</code>, but it is rarely seen in use. Here is a quick example of how to use it within an <code>INSERT</code> statement.</p>
<p>Let&#8217;s setup our table structure first:</p>
<pre>IF EXISTS (SELECT * FROM sys.tables WHERE name = 'users')
BEGIN
  DROP TABLE [users];
END;

CREATE TABLE [users] (
  [user_id] INT PRIMARY KEY IDENTITY(1,1),
  username VARCHAR(16),
  [password] VARCHAR(16),
  email VARCHAR(128)
);

IF EXISTS (SELECT * FROM sys.tables WHERE name = 'login_activity')
BEGIN
  DROP TABLE [login_activity];
END;

CREATE TABLE [login_activity] (
  user_id INT,
  user_ip VARCHAR(15),
  login_username VARCHAR(16),
  login_success BIT,
  login_time DATETIME
);</pre>
<p>Let&#8217;s assume we want an <code>addUser</code> procedure to create a user, log in said user, and return the new user&#8217;s <code>user_id</code>. Here is how we could do that with the <code>OUTPUT</code> clause:</p>
<pre>
CREATE PROC addUser
  @user_ip VARCHAR(15),
  @username VARCHAR(16),
  @password VARCHAR(16),
  @email VARCHAR(128)
AS

SET NOCOUNT ON;

CREATE TABLE #new_user(user_id INT);

INSERT INTO users (username, [password], email)
OUTPUT inserted.[user_id] INTO #new_user(user_id)
VALUES (@username, @password, @email);

INSERT INTO login_activity(user_id, login_ip, login_username,
  login_success, login_time)
SELECT user_id, @username, @user_ip, 1, CURRENT_TIMESTAMP
FROM #new_user;

SET NOCOUNT OFF;

SELECT user_id
FROM new_user;
</pre>
<pre>
EXEC [addUser] @user_ip = '192.168.1.1',
  @username = 'bob',
  @password = 'bob!password',
  @email = 'bob@gmail.com';

user_id
-----------
1

EXEC [addUser] @user_ip = '192.168.1.2',
  @username = 'john',
  @password = 'john!password',
  @email = 'john@yahoo.com';

user_id
-----------
2
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/05/dont-forget-the-output-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Paging Stored Procedure in MS SQL, By Page</title>
		<link>http://www.discreteinformation.com/2009/05/ms-sql-server-paging-method-1/</link>
		<comments>http://www.discreteinformation.com/2009/05/ms-sql-server-paging-method-1/#comments</comments>
		<pubDate>Sun, 24 May 2009 19:31:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[Pagination]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=15</guid>
		<description><![CDATA[MS SQL has the TOP clause, and it works very similar to MySQL&#8217;s LIMIT clause. However, the TOP clause in MS SQL provides no sort of OFFSET equivalent. Thus the TOP clause is virtually useless for a proper paging control. Let&#8217;s see one way we can work around that limitation:
For reference, here are the CREATE [...]]]></description>
			<content:encoded><![CDATA[<p>MS SQL has the <code>TOP</code> clause, and it works very similar to MySQL&#8217;s <code>LIMIT</code> clause. However, the <code>TOP</code> clause in MS SQL provides no sort of <code>OFFSET</code> equivalent. Thus the <code>TOP</code> clause is virtually useless for a proper paging control. Let&#8217;s see one way we can work around that limitation:</p>
<p>For reference, here are the <code>CREATE</code> and <code>INSERT</code> statements for the <code>[users]</code> table used in this example.</p>
<pre>
CREATE TABLE [users] (
  user_id INT PRIMARY KEY,
  username VARCHAR(16),
  password VARCHAR(16),
  email VARCHAR(128)
);

INSERT INTO [users] (user_id, username, password, email)
SELECT 1, 'bob', 'bob!password', 'bob@gmail.com'
UNION ALL
SELECT 2, 'john', 'john!password', 'john@yahoo.com'
UNION ALL
SELECT 3, 'kim', 'kim!password', 'kim@msn.com'
UNION ALL
SELECT 4, 'rachel', 'rachel!password', 'rachel@aol.com'
UNION ALL
SELECT 5, 'frank', 'frank!password', 'frank@email.com';
</pre>
<p>Now, let&#8217;s create a stored procedure to search our <code>[users]</code> table. It takes three paramaters. The <code>@email</code> paramater is a full or partial e-mail to search. <code>@page</code> is the page to be displayed, and <code>@per_page</code> is the number of results per page.</p>
<pre>
CREATE PROC searchUsersByEmail
  @email VARCHAR(128),
  @page SMALLINT,
  @per_page SMALLINT
AS

SET @last_page = (@nbr_results - 1) / @per_page + 1;

SELECT
  @nbr_results = COUNT(*)
FROM [users] AS u
WHERE u.email LIKE '%' + @email + '%';

SET @last_page = @nbr_results / @per_page; 

IF (@page = 1)
BEGIN
  -- Special first page case:
  SELECT TOP (@per_page)
    u.user_id,
    u.username,
    u.email
  FROM [users] AS u
  WHERE u.email LIKE '%' + @email + '%'
  ORDER BY u.email ASC;
END;
ELSE IF (@page = @last_page)
BEGIN
  -- Special last page case:
  SELECT s0.*
  FROM (
    SELECT TOP (@nbr_results - (@last_page - 1) * @per_page)
      u.user_id,
      u.username,
      u.email
    FROM [users] AS u
    WHERE u.email LIKE '%' + @email + '%'
    ORDER BY u.email DESC
  ) AS s0
  ORDER BY s0.email ASC;
END;
ELSE IF (@page > @last_page)
BEGIN
  -- Error / Empty set case, replace with error if desired.
  SELECT
    u.user_id,
    u.username,
    u.email
  FROM [users] AS u
  WHERE 1 = 0;
END;
ELSE
BEGIN
  -- All other cases:
  SELECT s1.*
  FROM (
    SELECT TOP (@per_page) s0.*
    FROM (
      SELECT TOP (@page * @per_page)
        u.user_id,
        u.username,
        u.email
      FROM [users] AS u
      WHERE u.email LIKE '%' + @email + '%'
      ORDER BY u.email ASC
    ) AS s0
    ORDER BY s0.email DESC
  ) AS s1
  ORDER BY s1.email ASC;
END;
</pre>
<p>Now let&#8217;s test our search procedure by searching for all e-mails with &#8220;.com&#8221;:</p>
<pre>
[searchUsersByEmail] @email = '.com', @page = 1, @per_page = 3;

user_id     username email
----------- -------- ----------------
1           bob      bob@gmail.com
5           frank    frank@email.com
2           john     john@yahoo.com

[searchUsersByEmail] @email = '.com', @page = 2, @per_page = 3;

user_id     username email
----------- -------- ----------------
3           kim      kim@msn.com
4           rachel   rachel@aol.com
</pre>
<p>That&#8217;s it. Now you have a functional procedure in MS SQL as an alternative to MySQL&#8217;s <code>LIMIT x OFFSET y</code> clause.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/05/ms-sql-server-paging-method-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Link MySQL to 64-bit MS SQL Server</title>
		<link>http://www.discreteinformation.com/2009/05/link-mysql-to-64-bit-ms-sql-server/</link>
		<comments>http://www.discreteinformation.com/2009/05/link-mysql-to-64-bit-ms-sql-server/#comments</comments>
		<pubDate>Thu, 21 May 2009 03:28:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[ODBC]]></category>

		<guid isPermaLink="false">http://www.discreteinformation.com/?p=9</guid>
		<description><![CDATA[The key to adding a MySQL instance as a linked server within 64-bit MS SQL Server is finding an appropriate x64 ODBC provider. Microsoft had previously depreciated and eliminated this feature for the 64-bit version of SQL Server.
They recently reversed their decision, and claim no new plans to depreciate this provider. However, the link is [...]]]></description>
			<content:encoded><![CDATA[<p>The key to adding a MySQL instance as a linked server within 64-bit MS SQL Server is finding an appropriate x64 ODBC provider. Microsoft had previously depreciated and eliminated this feature for the 64-bit version of SQL Server.</p>
<p>They recently reversed their decision, and claim no new plans to depreciate this provider. However, the link is slightly hidden. Here it is: <a title="64-Bit OLEDB Provider for ODBC (MSDASQL)" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=000364db-5e8b-44a8-b9be-ca44d18b059b&amp;displaylang=en" target="_blank">http://www.microsoft.com/downloads/details.aspx?FamilyID=000364db-5e8b-44a8-b9be-ca44d18b059b&amp;displaylang=en</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/05/link-mysql-to-64-bit-ms-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://www.discreteinformation.com/2009/05/hello-world/</link>
		<comments>http://www.discreteinformation.com/2009/05/hello-world/#comments</comments>
		<pubDate>Thu, 21 May 2009 00:57:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://discreteinformation.com/?p=1</guid>
		<description><![CDATA[Welcome to Discrete Information. The information stream will begin shortly.
]]></description>
			<content:encoded><![CDATA[<p>Welcome to Discrete Information. The information stream will begin shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.discreteinformation.com/2009/05/hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
