Index: test/dialect/mssql.py
===================================================================
--- test/dialect/mssql.py	(revision 3829)
+++ test/dialect/mssql.py	(working copy)
@@ -52,6 +52,38 @@
         m = MetaData()
         t = Table('sometable', m, Column('col1', Integer), Column('col2', Integer))
         self.assert_compile(select([func.max(t.c.col1)]), "SELECT max(sometable.col1) AS max_1 FROM sometable")
+
+    def test_limit(self):
+        t = table('sometable', column('col1'), column('col2'))
+
+        s = select([t]).limit(10).offset(20).order_by(t.c.col1).apply_labels()
+
+        self.assert_compile(s, "SELECT anon_1.sometable_col1 AS sometable_col1, anon_1.sometable_col2 AS sometable_col2 FROM (SELECT sometable.col1 AS sometable_col1, sometable.col2 AS sometable_col2, "
+            "ROW_NUMBER() OVER (ORDER BY sometable.col1) AS mssql_rn FROM sometable) AS anon_1 WHERE mssql_rn>20 AND mssql_rn<=30"
+        )
+
+        s = select([t]).limit(10).offset(20).order_by(t.c.col1)
+
+        self.assert_compile(s, "SELECT anon_1.col1 AS col1, anon_1.col2 AS col2 FROM (SELECT sometable.col1 AS col1, sometable.col2 AS col2, "
+            "ROW_NUMBER() OVER (ORDER BY sometable.col1) AS mssql_rn FROM sometable) AS anon_1 WHERE mssql_rn>20 AND mssql_rn<=30"
+        )
+
+        s = select([s.c.col1, s.c.col2])
+
+        self.assert_compile(s, "SELECT col1, col2 FROM (SELECT anon_1.col1 AS col1, anon_1.col2 AS col2 FROM "
+            "(SELECT sometable.col1 AS col1, sometable.col2 AS col2, ROW_NUMBER() OVER (ORDER BY sometable.col1) AS mssql_rn FROM sometable) AS anon_1 "
+            "WHERE mssql_rn>20 AND mssql_rn<=30)")
+
+        # testing this twice to ensure oracle doesn't modify the original statement 
+        self.assert_compile(s, "SELECT col1, col2 FROM (SELECT anon_1.col1 AS col1, anon_1.col2 AS col2 FROM "
+            "(SELECT sometable.col1 AS col1, sometable.col2 AS col2, ROW_NUMBER() OVER (ORDER BY sometable.col1) AS mssql_rn FROM sometable) AS anon_1 "
+            "WHERE mssql_rn>20 AND mssql_rn<=30)")
+
+        s = select([t]).limit(10).offset(20).order_by(t.c.col2)
+
+        self.assert_compile(s, "SELECT anon_1.col1 AS col1, anon_1.col2 AS col2 FROM (SELECT sometable.col1 AS col1, "
+            "sometable.col2 AS col2, ROW_NUMBER() OVER (ORDER BY sometable.col2) AS mssql_rn FROM sometable) AS anon_1 WHERE mssql_rn>20 AND mssql_rn<=30")
+
         
 if __name__ == "__main__":
     testbase.main()
Index: lib/sqlalchemy/databases/mssql.py
===================================================================
--- lib/sqlalchemy/databases/mssql.py	(revision 3829)
+++ lib/sqlalchemy/databases/mssql.py	(working copy)
@@ -877,8 +877,6 @@
         s = select._distinct and "DISTINCT " or ""
         if select._limit:
             s += "TOP %s " % (select._limit,)
-        if select._offset:
-            raise exceptions.InvalidRequestError('MSSQL does not support LIMIT with an offset')
         return s
 
     def limit_clause(self, select):    
@@ -951,7 +949,37 @@
         else:
             return ""
 
+    def visit_select(self, select, **kwargs):
+        """Look for OFFSET in a select statement, and if so tries to wrap 
+        it in a subquery with ``row_number()`` criterion.
+        """
 
+        if not getattr(select, '_mssql_visit', None) and select._offset is not None:
+            # to use ROW_NUMBER(), an ORDER BY is required.
+            orderby = self.process(select._order_by_clause)
+            if not orderby:
+                raise exceptions.InvalidRequestError("OFFSET in MS-SQL requires an ORDER BY clause")
+                
+            oldselect = select
+            select = select.column(sql.literal_column("ROW_NUMBER() OVER (ORDER BY %s)" % orderby).label("mssql_rn")).order_by(None)
+            select._mssql_visit = True
+
+            select_alias = select.alias()
+            limitselect = sql.select([c.label(list(c.proxies)[0].name) for c in select_alias.c if c.key!='mssql_rn'])
+            #limitselect._order_by_clause = select._order_by_clause
+            select._order_by_clause = expression.ClauseList(None)
+
+            if select._offset is not None:
+                limitselect.append_whereclause("mssql_rn>%d" % select._offset)
+                if select._limit is not None:
+                    limitselect.append_whereclause("mssql_rn<=%d" % (select._limit + select._offset))
+                    select._limit = None
+            return self.process(limitselect, **kwargs)
+        else:
+            return compiler.DefaultCompiler.visit_select(self, select, **kwargs)
+
+
+
 class MSSQLSchemaGenerator(compiler.SchemaGenerator):
     def get_column_specification(self, column, **kwargs):
         colspec = self.preparer.format_column(column) + " " + column.type.dialect_impl(self.dialect).get_col_spec()
