Aug 11 2010

Select DataSet and number of total rows with one stored procedure

when you want to write a search using .net and MSSQL, it’s a pain. This is because you’re forced to select every row in the table and then only display a small subset of it. This works okay for tables that have a few hundred rows, as query caching can make this faster. But what happens when you’re searching a table with half a million rows?

Unless you’re a complete masochist, you’re doing to want to split this into a more manageable data set, otherwise you’re gonna eat all the memory on your server. But this means that you can no longer use the DataSet.Tables[0].Rows.Count property to figure out how many rows you have. You can write a second stored procedure that’ll count the rows. But who wants to clog up their database with tons of stored procedures for no reason? Let’s consolidate it into one.

So what does this look like?

First: the stored procedure.

We’ll use output parameters to pass the row count back to our code


create procedure [dbo].[Search]
@searchText varchar(512), @recordsToReturn INT, @pageNumber INT, @numberofrows INT OUTPUT
AS

-- get the page we want to view
select * from
(
select *, ROW_NUMBER() OVER (ORDER BY creation_timestamp DESC) AS row from [table] where [table].columnName like '%' + @searchText + '%'
)
AS results WHERE row between (@pageNumber - 1) * @recordsToReturn + 1 and @pageNumber*@recordsToReturn;

-- get the total number of rows, not just the subset we want
set @numberofrows = (select count(*) from [table] where [table].columnName like '%' + @searchText + '%')

END

Now the C# (this’ll work in VB too, but feel free to convert it yourself)


SqlConnection conn = new SqlConnection();
conn.ConnectionString = ".....your connection string here.....";
conn.Open();

DataSet returnData = new DataSet();

SqlDataAdapter da = new SqlDataAdapter( "SearchMessages", conn);
da.SelectCommand.CommandType = CommandType.StoredProcedure;

da.SelectCommand.Parameters.Add("@searchText", SqlDbType.VarChar).Value = "bob";
da.SelectCommand.Parameters.Add("@recordsToReturn", SqlDbType.Int).Value = 10;
da.SelectCommand.Parameters.Add("@pageNumber", SqlDbType.Int).Value = 1;

//number of rows
SqlParameter outputParameter = new SqlParameter("@numberofrows", SqlDbType.Int, 2);
outputParameter.Direction = ParameterDirection.Output;

da.SelectCommand.Parameters.Add(outputParameter);

da.Fill(returnData, "theData");

int numberOfRowsInDataSet = (int)outputParameter.Value;

da.Dispose();
conn.Close();

Best of luck! As always, leave a message in the comments if you have questions


Jun 17 2010

Batch Delete Performance SQL Server

Deleting old records from a table with > 3 000 00 rows. What’s the best way to do this?

It seems the fastest way to do this is simply to:

delete from [table] where creation_timestamp < dateadd (mm, -6, getdate())

(deleting anything older than 6 months)

It took 3 hours (10916 seconds to be exact) to delete 1.6 million (1,619,433) records this way. (148.35 / second).

We needed to do a second batch the next day, but wanted to split it into batches to try to get better performance.

Running:


delete from [table] where pk_id in(
select pk_id from (
SELECT ROW_NUMBER() OVER (ORDER BY creation_timestamp desc) AS RowNumber, pk_id
FROM [table]
where creation_timestamp < '2009-12-16 13:52:08.673') _objectsToDelete
WHERE RowNumber between 1 and 100000)

takes 12 minutes. (732 seconds) (136.61 / second).

Strangely, using the TOP command with a subquery takes the longest:


delete from [table] where pk_id in (select TOP 100000 pk_id from [table] where creation_timestamp < '2009-12-16 13:52:08.673')

15 minutes (904 seconds) (110.61 / second)

Have a better way? Let me know in the comments!


Mar 15 2010

Pure PHP Pagination

So, for a while I’ve been looking for a ridiculously simple way to paginate data stored in a table. And while I love PHP, it just doesn’t come with some of the free things I take for granted in .Net

Today, while working on a pretty simple plugin, I wanted to add this functionality, and I didn’t want to waste a bunch of time. I was given a link to this great script: http://www.warkensoft.com/2009/12/paginated-navigation-bar/

It took me about a minute to implement the functionality. I then spent another 5 minutes doing CSS and that was it. Done. I’m not usually one for link sharing, but this made my life much easier. Hopefully it can make yours easier too.

The solution is pure PHP, no javascript required. Some day, I may try to expand upon this to include javascripty goodness, because that’s pretty much the only thing that could make it better


Mar 5 2010

ASP.Net 301 Redirect


<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://www.new-url.com");
}
</script>


Jan 20 2010

mysql command doesn’t work in OS X snow leopard

So you install mySql on your mac, and it’s working great, but then you go into terminal to run a mysqldump or something, and it doesn’t work!

you get a message something like:

-bash: mysqldump: command not found

so how do you fix this? well, copy and paste the following into your terminal window and press enter:

echo export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH" >> ~/.profile

source ~/.profile

whoa, whoa, you say. what is this doing? It makes it so that when you type any command into the terminal, it does a check of these folders before giving you the “command not found” error.

If you want to undo it, you can always edit your .profile, or just delete it.


Jan 12 2010

WordPress on Snow Leopard: Unable to Connect to Database

If an “unable to connect to database” comes up while installing WordPress on a Snow Leopard machine, try adding :3306 to the end of the DB_HOST in wp-config.php

Assuming everything else works, this should solve your problem!


Jan 11 2010

Run JavaScript function every n seconds


//tell javascript to run a function in 1 second
setTimeout ("myFunction()", 1000 );

function myFunction(){
//do stuff

//once the function is finished, queue this function up to run again in 1 second
setTimeout ( "myFunction()", 1000 );
}


Sep 12 2009

Get latitude and longitude of an address using google maps

Google doesn’t make it easy to show you the latitude and longitude of an address you search in google maps, but there’s an easy way to get the info.

  1. go to google maps, type the address, and click search
  2. once you’ve found it, go to your address bar and clear what’s in it
  3. paste: javascript:void(prompt('',gApplication.getMap().getCenter())); into the address bar
  4. use the coordinates for whatever you wish!

Aug 13 2009

VirtualHostX and mod_rewrite

To enable mod_rewrite manually, see: OS X server tips but if you are using VirtualHostX it changes your default config file. Add the following code to the Directives box:


Options FollowSymLinks
AllowOverride All AuthConfig
Order deny,allow
Deny from all

if you’re using the new version of VirtualHostX, make sure that you select Directory from the dropdown, then use:


Options FollowSymLinks
AllowOverride All AuthConfig


Jul 8 2009

Embedding Web Fonts: A cautionary tale

So for work, the designer says “Hey, can we use this font in the webpage” and like an idiot, I say “sure, why not?”. Well, FF and Safari don’t support .otf files (for whatever reason) So I download FontForge, open it in X11 (on my mac) and convert it to .ttf, which works great.

Then I messed around in IE, trying to make it work, even downloading this tool:

Microsoft WEFT

Worst thing EVER. Don’t do this. Don’t get this. Don’t even look at this. You will feel violated if you use it.

So…how to embed an OTF font in a website (make sure you have a license to do so kids):

  1. Convert OTF file to .ttf (use fontForge)
  2. Embed with @font-face
  3. When adding the font to a style, in IE you CAN NOT call it by the name you gave it with the @font-face declaration. You have to call it by it’s name. So if the font’s name is myfontLTSTDBOLDITALICROMAN you have to do: body{ font-family: myfontLTSTDBOLDITALICROMAN; } Sucky? Very. Works? yes.

Have a nice day