| |
|
If this is your first visit, be sure to check out the FAQ by clicking the link above.
You may have to register before you can post: click the register link above to proceed.
To start viewing messages, select the forum that you want to visit from the selection below.
|
 |
|

11-02-09, 23:44
|
|
Registered User
|
|
Join Date: Nov 2009
Location: Selangor, Malaysia
Posts: 5
|
|
Paging Stored Procedure
|
|
I need to create a paging result in SQL Server 2000. I already create the stored proc but the result is error. "Invalid Syntax near keyword FROM"
This is the stored Proc.
CREATE PROCEDURE UserPaging(@sqlStr varchar(5000), @orderBy varchar(1000), @startRow int, @endRow int)
AS
DECLARE @Out int, @SQLSTRING varchar(5000)
DECLARE @fieldName varchar(1000)
DECLARE @tableName varchar(1000)
DECLARE @pageSize int
SET @pageSize = @endRow - @startRow
SET @fieldName = SUBSTRING(@sqlStr, 8, PATINDEX('%from%', @sqlStr) - 8)
SET @tableName = SUBSTRING(@sqlStr, PATINDEX('%from%', @sqlStr), 4)
SET NOCOUNT ON
SET @SQLSTRING = N'select '+@fieldName+' from ( SELECT TOP '+ CAST(@pageSize as varchar(10)) + ' ' + @fieldName + ' from (SELECT TOP ' + CAST(@endRow as varchar(10)) +
' ' + @fieldName + ' FROM (SELECT TOP ' + CAST(@endRow as varchar(10)) +
' ' + @fieldName + ' FROM ' +@tableName + ' as T1
ORDER BY ' + @orderBy + ') AS T2 ORDER BY ' + @orderBy + ' DESC ) AS T3) As T4 ORDER BY ' + @orderBy + ' ASC'
SET @SQLSTRING = @fieldName
EXEC(@SQLSTRING)
RETURN
GO
The Java application that call this stored proc can only provide this parameter : String sql, String orderBy, int startRow, int endRow
From what i see, im quite sure that the error is most probably came from the substring function that i use. But when i test in query designer "select SUBSTRING('select id, name, email from user', 8, PATINDEX('%from%', 'select id, name, email from user') - 8)", there is no error....
Or, if anyone have other best way to create stored proc for paging?

|
|

11-03-09, 08:50
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
Try adding PRINT @SQLString before you exec, to aid in debugging.
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|

11-03-09, 08:51
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
|
|
...and this stored procedure is just begging to be hacked by sql injection.
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|

11-03-09, 09:38
|
|
Window Washer
|
|
Join Date: Nov 2002
Location: Jersey
Posts: 10,303
|
|
Quote:
Originally Posted by blindman
Try adding PRINT @SQLString before you exec, to aid in debugging.
|
That's your advice?
Dynamic paging for dynamic queries?
oye
|
|

11-03-09, 10:19
|
|
Registered User
|
|
Join Date: Nov 2004
Posts: 1,279
|
|
Apart from the possible SQL-injection vulnerability, I don't think the logic behind your query is correct. Somewhere you should filter out records that come before @startRow. I see three "SELECT TOP" in a row, it just doesn't give me a warm feeling about the correctness.
Just first try to make a query that does what you want, then start thinking of how to embed it in a sproc.
__________________
With kind regards . . . . . SQL Server 2000/2005/2008/2008 R2 Earned beers: 16
Wim
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
Grabel's Law: 2 is not equal to 3 -- not even for very large values of 2.
Pat Phelan's Law: 2 very definitely CAN equal 3 -- in at least two programming languages
|
|

11-03-09, 12:02
|
|
SQL Server Street Fighter
|
|
Join Date: Nov 2004
Location: Down The Rabbit Hole
Posts: 7,979
|
|
in my experience, whatever you do, server side paging in sql 2000 is ugly and slow. With CTEs in 2K5, it is awesome. In 2000 and I must have done it 8 different ways, it always stinks.
__________________
software development is where smart people go to waste their lives
|
|

11-03-09, 12:04
|
|
Window Washer
|
|
Join Date: Nov 2002
Location: Jersey
Posts: 10,303
|
|
well it would be easier if you knew what table you were working on....
|
|

11-03-09, 12:19
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
Quote:
Originally Posted by Brett Kaiser
That's your advice?
Dynamic paging for dynamic queries?
oye
|
That's my advice for debugging dynamic code.
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|

11-03-09, 12:19
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
Quote:
Originally Posted by Brett Kaiser
well it would be easier if you knew what table you were working on....
|
That's your advice?
(Sorry, could not resist.)
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|

11-03-09, 12:57
|
|
Window Washer
|
|
Join Date: Nov 2002
Location: Jersey
Posts: 10,303
|
|
Hey Look who found their cane and made it in the door
Quote:
Originally Posted by blindman
That's your advice?
(Sorry, could not resist.)
|
Yeah
It would help if I had the DDL of the table (including Indexes and constraints) that I was working with
|
|

11-03-09, 21:55
|
|
Registered User
|
|
Join Date: Nov 2009
Location: Selangor, Malaysia
Posts: 5
|
|
Thanks all for your reply, i cannot specify which table because this project is our product and the table name is always changing depend to client's database. Currently, we support database for DB2, MySql, SQL Server 2005, and now im working on SQL Server 2000.
I already remove the stored proc from the db and put the sql query inside the Java code and it work. The only concern is the time. It getting slower and slower when moving to the last page. It took about 1.5 second to query for the last page that have 1million records!! 
|
|

11-04-09, 09:04
|
|
Registered User
|
|
Join Date: Nov 2004
Posts: 1,279
|
|
Code:
CREATE PROCEDURE dbo.UserPaging(
@sqlStr varchar(5000),
@orderBy varchar(1000),
@startRow int,
@endRow int
)
AS
SET NOCOUNT ON
DECLARE @SQLSTRING varchar(5000)
DECLARE @fieldName varchar(1000)
DECLARE @tableName varchar(1000)
SET @fieldName = SUBSTRING(@sqlStr, 8, PATINDEX('%from%', @sqlStr) - 8)
SET @tableName = RIGHT(@sqlStr, PATINDEX('%from%', @sqlStr) + 6)
SET @SQLSTRING = N'WITH cte (' + @fieldName + '
,___RowNUmber___) AS
(SELECT ' + @fieldName + ', ROW_NUMBER() OVER (ORDER BY ' + @orderBy + ') AS ___RowNUmber___
' + @tableName + ')
SELECT ' + @fieldName + '
FROM cte
WHERE ___RowNUmber___ BETWEEN ' + CAST(@startRow as varchar(12)) + ' AND ' + CAST(@endRow as varchar(12)) + ''
-- PRINT '@fieldName = ' + @fieldName
-- PRINT '@tableName = ' + @tableName
-- PRINT @SQLSTRING
EXEC(@SQLSTRING)
SET NOCOUNT OFF
RETURN
GO
CREATE TABLE DaTable(
Id int identity (1, 1) not null,
column1 char(10) NOT NULL,
CONSTRAINT PK_DaTable PRIMARY KEY (Id)
)
GO
CREATE FUNCTION dbo.GenerateNumList(
@MaxNum Int
)
RETURNS TABLE
AS
RETURN
WITH cte (num) AS
(SELECT 0
UNION ALL
SELECT num + 1
FROM cte
WHERE num < @MaxNum
)
SELECT num
FROM cte
GO
INSERT INTO DaTable(column1)
SELECT 'bla' + CAST(num AS CHAR(10))
FROM dbo.GenerateNumList(10)
EXECUTE dbo.UserPaging 'SELECT Id, column1 FROM DaTable where Id > -1', 'Id', 7, 10
GO
/*WITH cte (Id, column1, ___RowNUmber___) AS
(SELECT Id, column1
, ROW_NUMBER() OVER (ORDER BY column1) as ___RowNUmber___
FROM DaTable
)
SELECT Id, column1
FROM cte
WHERE ___RowNUmber___ BETWEEN 7 AND 10
*/
DROP PROCEDURE dbo.UserPaging
GO
DROP TABLE DaTable
GO
DROP FUNCTION dbo.GenerateNumList
GO
It works, but it has some severe limitations:
- vulnerability for SQL injection
- vulnerability due to weak parsing logic of the SQL query (suppose you have a column that is called NomDe Fromage (CheeseName) appearing in the SELECT. How would the resulting "paging SQL" look like?) At least alter the interface so you don't have to parse for the @fieldName and @tableName in the sproc. You already did it for the ORDER BY part.
__________________
With kind regards . . . . . SQL Server 2000/2005/2008/2008 R2 Earned beers: 16
Wim
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
Grabel's Law: 2 is not equal to 3 -- not even for very large values of 2.
Pat Phelan's Law: 2 very definitely CAN equal 3 -- in at least two programming languages
|
|

11-04-09, 10:21
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
This is throwing me for a loop:
Code:
SET @fieldName = SUBSTRING(@sqlStr, 8, PATINDEX('%from%', @sqlStr) - 8)
SET @tableName = SUBSTRING(@sqlStr, PATINDEX('%from%', @sqlStr), 4)
It looks very fragile and hackish. Can you give an example of the input for the @sqlStr parameter.
I really think your approach to this needs to be reconsidered.
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|

11-04-09, 21:29
|
|
Registered User
|
|
Join Date: Nov 2009
Location: Selangor, Malaysia
Posts: 5
|
|
Quote:
Originally Posted by blindman
This is throwing me for a loop:
Code:
SET @fieldName = SUBSTRING(@sqlStr, 8, PATINDEX('%from%', @sqlStr) - 8)
SET @tableName = SUBSTRING(@sqlStr, PATINDEX('%from%', @sqlStr), 4)
It looks very fragile and hackish. Can you give an example of the input for the @sqlStr parameter.
I really think your approach to this needs to be reconsidered.
|
Yeah i understand that bro. example of sql provided is "select user_id, name, email, age from users". From what i know, clients database field name could be named from reserved keyword. That is the problem. Let say if they have a field name "from". So, to query that table, "select user_id, name, from, email from users". That is the weakness of using my method.
|
|

11-05-09, 12:06
|
|
World Class Flame Warrior
|
|
Join Date: Jun 2003
Location: Ohio
Posts: 11,726
|
|
And it will also fail if they type double spaces between words, and who knows when else.
This approach is doomed to failure. Reexamine your business requirements and come up with something more robust than parsing strings entered by users.
__________________
If it's not practically useful, then it's practically useless.
blindman
www.chess.com: "sqlblindman"
|
|
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|