Benutzer mit den meisten Antworten
Anzahl selectierter Datensätze als output

Frage
-
Hallo zusammen,
ich möchte in asp.net ein Dataset mit pager erstellen und benötige hierzu die Gesamtanzahl der selectierten Datensätze. Diese fallen je nach Bedingungen unterschiedlich aus.Ich habe diese Prozedur mal als Vorlagen genommen.
ALTER PROCEDURE [dbo].[spx_PagerS]
@PageNo int = 1,
@ItemsPerPage int = 20,
@TotalRows int out
AS
BEGIN
SET NOCOUNT ON
DECLARE
@StartIdx int,
@SQL nvarchar(max),
@SQL_Conditions nvarchar(max),
@EndIdx int
IF @PageNo < 1 SET @PageNo = 1
IF @ItemsPerPage < 1 SET @ItemsPerPage = 10
SET @StartIdx = (@PageNo -1) * @ItemsPerPage + 1
SET @EndIdx = (@StartIdx + @ItemsPerPage) - 1
SET @SQL = 'with rsc as(SELECT kursid, themen
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY kursid) AS Row, *
FROM seminar where dokstatus <=2 ) AS tbl WHERE Row >= '
+ CONVERT(varchar(9), @StartIdx) + ' AND
Row <= ' + CONVERT(varchar(9), @EndIdx)+')'
set @sql = @sql + 'select * from rsc'
EXEC sp_executesql @SQL
SET @SQL = 'SELECT @TotalRows=COUNT(*) FROM rsc'
EXEC sp_executesql
@query = @SQL,
@params = N'@TotalRows INT OUTPUT',
@TotalRows = @TotalRows OUTPUT
ENDNach Ausführen der Prozedur wird mit ein Fehler in folgender Zeile ausgeworfen,
SET @SQL = 'SELECT @TotalRows=COUNT(*) FROM rsc'
Das Object 'rsc' ist nicht bekannt. Das ist mir auch verständlich.
Wie kann ich die Prozedur umschreiben, damit @totalrows mir die Anzahl der Datensätze auswirft, die tatsächlich selectiert worden sind ?
Ich würde mich über eine Antwort sehr freuen, ich such schon seit Tagen nach einer Lösung.
Liebe Grüße, die Luzie!
Antworten
-
Hallo Luzie,
wenn Du für das Hauptergebnis einen SqlDataAdapter verwendest, ist der Einsatz
von zwei SqlCommand Instanzen sinnvoller. Um den Ausgabeparameter zu erhalten,
benötigst Du keinen DataAdapter. Ein ExecuteNonQuery für das SqlCommmand
und abrufen des Parameters ("@TotalRows") danach reicht, siehe
Ändern von Daten mit gespeicherten Prozeduren (ADO.NET)
(das hier nichts geändert wird ist dafür ohne Belang).Was den Fehler bei der Parameterübergabe angeht:
Und die Meldung bezüglich der falschen Konvertierung resultiert daraus,
dass versucht wird, den @search-Parameter als @PageNo zu interpretieren.Alle bei sp_executesql verwendeten Parameter müssen in @paramlist
deklariert werden, und dann genau in der Reihenfolge aufgeführt werden.
Und bei Dir ist @search der Dritte (und nicht der 1.):SET @paramList = '@PageNo int, @ItemsPerPage int,@search varchar(255)'
Umgekehrt spielt es keine Rolle, ob der Parameter effektiv verwendet wird,
so dass Du auch mal einige "auf Vorrat" übergeben kannst.Gruß Elmar
- Als Antwort markiert Luzie Samstag, 12. Juni 2010 07:42
Alle Antworten
-
Hallo Luzie,
Deine RSC CTE ist nur beim ersten sp_executesql verfügbar,
die zweite Anweisung weiß davon nichts mehr.
Dort müsstest Du den SQL Text ebenfalls einfügen.Wovon ich aber abraten würde.
Denn nicht nur dass die Abfrage zweimal ausgeführt werden muß,
was nicht gerade geschwindigkeitsteigernd ist.
Ausgabevariablen stehen erst nach dem Abarbeiten aller Ergebnismengen
(hier der ersten Abfrage) zur Verfügung.
Wenn Du aber wiederum die Daten der ersten Abfrage verarbeitet hast,
kannst Du ohnehin feststellen, wieviele Zeilen Du gerade verarbeitet hast.
Womit die zweite Abfrage (und Ausgabevariable) flüssiger als flüssig ist.Deswegen ist es wesentlich sinnvoller einmal direkt abzufragen.
Zumal Du auch ganz ohne dynamisches SQL klarkommst:ALTER PROCEDURE [dbo].[spx_PagerS] @PageNo int = 1, @ItemsPerPage int = 20, @TotalRows int out AS BEGIN SET NOCOUNT ON DECLARE @StartIdx int, @EndIdx int IF @PageNo < 1 SET @PageNo = 1 IF @ItemsPerPage < 1 SET @ItemsPerPage = 10 SET @StartIdx = (@PageNo -1) * @ItemsPerPage + 1 SET @EndIdx = (@StartIdx + @ItemsPerPage) - 1; WITH rsc AS ( SELECT tbl.kursid, tbl.themen FROM (SELECT ROW_NUMBER() OVER(ORDER BY kursid) AS Row, kursid, themen FROM seminar WHERE dokstatus <= 2) AS tbl WHERE tbl.Row >= @StartIdx AND tbl.Row <= @EndIdx ) SELECT * FROM rsc; -- Immer noch überflüssig SET @TotalRows=@@ROWCOUNT; END
Das liest sich IMO gleich viel freundlicher (wenn auch ungetestet).
@TotalRows habe ich mehr der Vollständigkeit halber via @@ROWCOUNT befüllt,
aber notwendig wäre das nicht wie gesagt nicht.Gruß Elmar
-
Hallo Elmar,
erstmals vielen herzlichen Dank für die Antwort.
Mein Beispiel ist nur eine ganz abgespeckte Version der eigentlichen Prozedur. Ich traue mich gar nicht, die komplette Version hier zu posten, ihr schlagt bestimmt die Hände über dem Kopf zusammen, aber trotzdem, ich komme vermutlich um das dyn. SQL vermutlich nicht herum. Und diese muss noch um 2 zusätzliche Abfrgen erweitert werden, je nach Anforderung über den Paramter @sicht. Ich muss diese Sichten zur Laufzeit austauschen, weil die Verknüpfungen im Falle der Aufforderungen doppelte Datensätze (verschiedene Kategorien) ergeben müssen. Naja, das funktioniert auch, die ganze Prozedur funktioniert eigentlich.
Lediglich die Ausgabe der Anzahl der Datensätze, das bekomme ich nicht hin, und die brauche ich für die Generierung des Pagers.
SET @TotalRows=@@ROWCOUNT;
gibt mir ja immer nur die aktuelle Anzahl des Seitenaufrufs zurück und das sind nie mehr als 20 Datensätze, die Anzahl, die eben unter @ItemsPerPage angegeben ist, leider nicht die Gesamtanzahl :)
Aber für die Berechnung der Seitenaufrufe benötige ich die Gesamt-Anzahl.
Bpsw. die Abfrage ergibt eine Anzahl von 64 Datensätzen und diese durch @ItemsPerPage geteilt, ergibt max. 4 Durchläufe. Diese Berechnung brauche ich.
Hast Du noch eine Idee?
ALTER PROCEDURE [dbo].[sp_seminarPaging1]
@pageNo int = 1,
@ItemsPerPage int = 20,
@NEU bit = NULL,
@BS bit = NULL,
@CH bit = NULL,
@sort varchar(20) = 'beginn',
@search varchar(255) = '%',
@debug bit = 1,
@totalRows int out
AS
DECLARE @paramlist nvarchar(1000)
DECLARE @haswhere bit,
@StartIdx int,
@SQL nvarchar(max),
@SQL_Conditions nvarchar(max),
@EndIdx int,
@spalten varchar(300) = '',
@sicht varchar(300) = 'vSeminar'
IF @PageNo < 1 SET @PageNo = 1
IF @ItemsPerPage < 1 SET @ItemsPerPage = 10
SET @StartIdx = (@PageNo -1) * @ItemsPerPage + 1
SET @EndIdx = (@StartIdx + @ItemsPerPage) - 1
SET @SQL = 'with rsSeminar as
(
SELECT kursid, CONVERT(char(10), Beginn, 104)
AS Datum, themen,NEU,BS,CH,kat,zert,'
if @sort = 'beginn'
BEGIN
set @sql = @sql + 'DATENAME(MM, beginn) + '' '' + CAST(YEAR(beginn) AS VARCHAR(4))'
END
ELSE IF @sort = 'kat'
Begin
set @sql = @sql + 'kat'
END
ELSE IF @sort = 'usort'
Begin
set @sql = @sql + 'detail'
END
ELSE
BEGIN
set @sql = @sql + 'detail'
END
set @sql = @sql + ' AS sortvar
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY ' + @sort +',beginn ASC) AS Row, *
FROM '+@sicht+'
where (themen like ' + quotename('%' + @search + '%','''')+ '
or beschreibung like ' + quotename('%' + @search + '%','''')+ '
or kurztext like ' + quotename('%' + @search + '%','''')+ ')
) AS tbl WHERE Row >= '
+ CONVERT(varchar(9), @StartIdx) + ' AND
Row <= ' + CONVERT(varchar(9), @EndIdx)
--SET @hasWhere = 0
--IF @BS <> 0
--BEGIN
-- SET @sql = @sql + ' and (BS=1'
-- SET @hasWhere = 1
--END
--IF @NEU <> 0
--BEGIN
-- IF @hasWhere = 0
-- BEGIN
-- SET @sql = @sql + ' and (NEU=1'
-- SET @hasWhere = 1
-- end
-- ELSE
-- SET @sql = @sql + ' and NEU=1'
--END
--IF @CH <> 0
--BEGIN
-- IF @hasWhere = 0
-- BEGIN
-- SET @sql = @sql + ' and (CH=1'
-- SET @hasWhere = 1
-- END
-- ELSE
-- SET @sql = @sql + ' and CH=1'
--END
--IF @hasWhere = 1
--Begin
-- SET @sql = @sql + ')'
--END
set @SQL = @SQL +')'
SET @paramList = '@pageNo int,
@ItemsPerPage int'
IF @debug = 1 PRINT @sql
SET @sql = @sql + 'select * from rsSeminar'
EXEC sp_executesql
@sql,
@paramlist,
@pageNo,
@ItemsPerPage
set @sql = 'select @totalRows=count(*) from vSeminar'
EXEC sp_executesql
@query = @sql,
@params = N'@totalRows int output',
@totalrows = @totalRows Output -
Hallo Luzie,
wenn Du die Zahl für das Kriterum brauchst, wäre das sinnvollste zwei Abfragen zu verwenden,
und die Gesamtzahl für weitere Aufrufe zwischenspeichern - letztendlich kostet das weniger,
als den SQL Server die Abfrage erneut ausführen zu lassen.
Man kann es auch durch zwei getrennte Aufrufe lösen, was ich unten zeige -
um beides in einem Rutsch auszuführen, mußt Du nur das SQL etwas umstellen.Wichtig erschien mir aber auch die Parameter-Verkettung zu elemenieren -
nicht nur um SQL Injection vorzubeugen, sondern auch um das Cachen von
Abfrageplänen zu fördern. Die Suchparameter (@search) kann man ebenso
wie die übrigen Kriterien dem sp_executesql mitgeben.Vorne dran eine frei Nase zusammengestellte Tabelle...
USE tempdb; GO CREATE TABLE dbo.seminar ( kursid int not null, beginn datetime not null, themen varchar(255) null, detail varchar(255) null, kurztext varchar(255) null, beschreibung varchar(255) null, kat varchar(10) null, neu varchar(10) null, bs varchar(10) null, ch varchar(10) null, zert varchar(10) null) GO SET NOCOUNT ON; DECLARE @row int; SET @row = 1 WHILE @row <= 1000 BEGIN INSERT INTO dbo.seminar(kursid, beginn, themen) VALUES (@row, DATEADD(dd, @row % 30, GETDATE()), CASE @row % 3 WHEN 1 THEN 'einer' ELSE 'alle' END); SET @row += 1; END GO CREATE VIEW dbo.vseminar AS SELECT * FROM dbo.seminar; GO CREATE PROCEDURE [dbo].[sp_seminarPaging1] @pageNo int = 1, @ItemsPerPage int = 20, @NEU bit = NULL, @BS bit = NULL, @CH bit = NULL, @sort varchar(20) = 'beginn', @search varchar(255) = '%', @debug bit = 1, -- 1 = Anzahl liefern @gettotalRows bit = 0, @totalRows int = null OUT AS SET NOCOUNT ON; DECLARE @SQL nvarchar(max), @paramlist nvarchar(1000); DECLARE @sicht sysname= N'vSeminar'; DECLARE @StartIdx int, @EndIdx int; /* DECLARE @haswhere bit, @SQL_Conditions nvarchar(max), @spalten varchar(300) = ''; */ IF @PageNo < 1 SET @PageNo = 1 IF @ItemsPerPage < 1 SET @ItemsPerPage = 10 SET @StartIdx = (@PageNo -1) * @ItemsPerPage + 1 SET @EndIdx = (@StartIdx + @ItemsPerPage) - 1 DECLARE @partitionorder nvarchar(1024); -- OVER Klausel SET @partitionorder = N'beginn ASC' IF ISNULL(@sort, 'beginn') <> 'beginn' BEGIN SET @partitionorder = QUOTENAME(@sort) + N',' + @partitionorder END -- einmalig '%' IF @search <> '%' SET @search = '%' + ISNULL(@search, '') + '%' SET @SQL = N' WITH rsSeminar AS ( SELECT kursid, CONVERT(char(10), Beginn, 104) AS Datum, themen,NEU,BS,CH,kat,zert,'; SET @SQL = @SQL + CASE @sort WHEN 'beginn' THEN N'DATENAME(MM, beginn) + '' '' + CAST(YEAR(beginn) AS VARCHAR(4))' WHEN 'kat' THEN N'kat' WHEN 'usort' THEN N'detail' ELSE N'detail' END + ' AS sortvar'; SET @SQL = @SQL + N' FROM (SELECT ROW_NUMBER() OVER(ORDER BY ' + @sort + N') AS Row, * FROM ' + @sicht + N' WHERE (themen like @search OR beschreibung like @search OR kurztext like @search) ) AS tbl'; IF @gettotalRows = 0 BEGIN SET @SQL = @SQL + N' WHERE Row >= @StartIdx AND Row <= @EndIdx'; END; -- weitere Kriterien... SET @SQL = @SQL + N')'; IF @debug = 1 PRINT @sql; SET @paramList = N'@pageNo int, @ItemsPerPage int, @search varchar(257), @StartIdx int, @EndIdx int'; IF @gettotalRows = 1 BEGIN SET @SQL = @SQL + N' SELECT @TotalRows = COUNT(*) FROM rsSeminar;'; SET @paramlist = @paramlist + N', @totalRows int output'; EXEC sp_executesql @sql, @paramlist, @pageNo, @ItemsPerPage, @search, @StartIdx, @EndIdx, @totalRows OUT; END ELSE BEGIN SET @SQL = @SQL + N' SELECT * FROM rsSeminar;'; EXEC sp_executesql @sql, @paramlist, @pageNo, @ItemsPerPage, @search, @StartIdx, @EndIdx; END; RETURN 0; GO -- als geteilter Aufruf DECLARE @totalrows int; EXEC [dbo].[sp_seminarPaging1] @pageNo = 5, @ItemsPerPage = 20, @NEU = NULL, @BS = NULL, @CH = NULL, @sort = 'beginn', @search = '%', @debug = 1; EXEC [dbo].[sp_seminarPaging1] @NEU = NULL, @BS = NULL, @CH = NULL, @sort = 'beginn', @search = '%', @debug = 1, @gettotalrows = 1, @totalrows = @totalrows OUT SELECT @totalrows AS Rows
Gruß Elmar -
Lieber Elmar,
vielen Dank für die Mühe und auch für die Anregungen. Ich kann es kaum fassen. :)
Ich habe es auch ausprobiert und es läuft super schön. Allerdings ist mir nicht so richtig klar, wie ich den doppelten Aufruf umsetzen kann. Ich müsste somit in ASP.NET das ganze Verbindungsprozedure doppelt ausführen?
Das verstehe ich jetzt nicht so richtig, tut mir leid. Ich würde natürlich liebend gerne ein schnelles sichers Scirpt verwenden. Ich sitze da nämlich jetzt schon mehr als eine Woche dran und bekomme bald die ganz dunkelrote Karte, wenn ich jetzt nicht aus den Puschen komme. Ich bin leider keine routinierte Programmiererin, weder in TSQL noch in ASP.NET ;(
Meine Prozedur sieht wie folgt aus. Sie läuft auch. An Datensätzen habe ich nicht viel zu verwalten, aber die sind alle so kompliziert verknüpft und in vielen Kategorien und Unterkategorien verteilt, das macht den Aufbau für mich jetzt sehr schwierig.
Ich würde es schon sehr gerne umsetzen, so wie Du es vorschlägst, aber vorerst muss ich meines verwenden. Würdest Du da nochmal drüber schauen, ob es eine Sicherheitslücke gibt?
USE [ptsService]
GO
/****** Object: StoredProcedure [dbo].[spx_PagerN] Script Date: 06/09/2010 17:41:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spx_PagerN]
@PageNo int = 1,
@ItemsPerPage int = 20,
@kat varchar(10) = '%',
@NEU bit = NULL,
@BS bit = NULL,
@CH bit = NULL,
@sort varchar(20) = 'beginn',
@debug bit = 0,
@search varchar(255) = '%',
@detailid int = null,
@buchid int = null,
@kursid int = null,
@buch int = null,
--@zert int = null,
@ks varchar(10) = null,
@TotalRows int out
AS
BEGIN
SET NOCOUNT ON
DECLARE
@sql nvarchar(4000),
@sicht nvarchar(30),
@where nvarchar(1000),
@paramlist nvarchar(1000),
@spalten nvarchar(100) = ',''0'' as detailtext',
@haswhere bit
set @sicht = 'vSeminarGesamt'
if @detailid > 0
BEGIN
set @sicht = 'vSeminarDetailGesamt'
set @spalten = ',detail, dDetail, usort,cdetailid, detailtext '
END
if @buchid >0
BEGIN
set @sicht = 'vSeminarBuch'
set @spalten = ',buchid, thema, verlagName '
END
set @where = ' where beginn >=getdate() and '
IF @kursid > 1
BEGIN
set @PageNo = 1
set @ItemsPerPage = 500
SET @where = @where + 'kursid like '+QUOTENAME(@kursid,'''')
END
ELSE
Begin
set @where = @where + '(themen like ' + quotename('%' + @search + '%','''')+ '
or beschreibung like ' + quotename('%' + @search + '%','''')+ '
or kurztext like ' + quotename('%' + @search + '%','''')+ ')
and dokstatus <=2'
IF @detailid > 0
BEGIN
SET @where = @where + ' and cdetailid like '+QUOTENAME(@detailid,'''')
END
SET @hasWhere = 0
IF @BS <> 0
BEGIN
SET @where = @where + ' and (BS=1'
SET @hasWhere = 1
END
IF @ks <> '0'
BEGIN
IF @hasWhere = 0
BEGIN
SET @where = @where + ' and (kontaktstudium <> "0"'
SET @hasWhere = 1
end
ELSE
SET @sql = @sql + ' and kontaktstudium <> "0"'
END
IF @NEU <> 0
BEGIN
IF @hasWhere = 0
BEGIN
SET @where = @where + ' and (NEU=1'
SET @hasWhere = 1
end
ELSE
SET @where = @where + ' and NEU=1'
END
IF @CH <> 0
BEGIN
IF @hasWhere = 0
BEGIN
SET @where = @where + ' and (CH=1'
SET @hasWhere = 1
END
ELSE
SET @sql = @sql + ' and CH=1'
END
IF @hasWhere = 1
Begin
SET @where = @where + ')'
END
END
SET @sql = 'SET QUOTED_IDENTIFIER OFF
WITH rsContacts as
(
SELECT distinct ROW_NUMBER() OVER(ORDER BY ' + @sort +',beginn ASC)
AS [RowNr],'
if @sort = 'beginn'
BEGIN
set @sql = @sql + 'DATENAME(MM, beginn) + '' '' + CAST(YEAR(beginn) AS VARCHAR(4))'
END
ELSE IF @sort = 'kat'
Begin
set @sql = @sql + 'kat'
END
ELSE IF @sort = 'usort'
Begin
set @sql = @sql + 'detail'
END
ELSE
BEGIN
set @sql = @sql + 'detail'
END
set @sql = @sql + ' AS sortvar,
kursid, CONVERT(char(10), Beginn, 104) AS Datum, themen,kontaktstudium,NEU,BS,CH,kat,
buch,zert,kTitel, detailid '+@spalten +'
FROM ' + @sicht+ @where +') '
SET @sql = @sql + '
SELECT distinct * FROM rsContacts
WHERE RowNr BETWEEN (@PageNo - 1) * @ItemsPerPage + 1
AND @PageNo * @ItemsPerPage'
SET @paramList = '@PageNo int,
@ItemsPerPage int'
IF @debug = 1 PRINT @sql
EXEC sp_executesql
@sql,
@paramlist,
@PageNo,
@ItemsPerPage
SET @SQL = 'SELECT @TotalRows=COUNT(*) FROM '+@sicht+@where
EXEC sp_executesql
@query = @SQL,
@params = N'@TotalRows INT OUTPUT',
@TotalRows = @TotalRows OUTPUT
END
Liebe Grüße, die Luzie! -
Hallo Luzie,
wenn Du eine Verbindung offen hast, kannst Du zwei Aufrufe
hintereinander absetzen und da die Paramter gleich sind, reicht
eine (Sql)Command Instanz - wobei Du zuerst @TotalRows abfragen
speichern solltest. Bei weiteren Fragen dazu => ASP.NET Forum,
wobei Du den derzeitigen Zugriff erläutern solltest - Stefan und Co.
können dazu mehr sagen als ich (der nicht sonderlich webaffin ist).Du kannst es (und ich würde es auch) stückweise umbauen,
um vorhandene Funktionalität nicht aus Versehen zu "demolieren".So wäre ein erster Schritt, Parameter (wie bei @search) einzusetzen.
Zum Sicherheitsrisiko kann ich nur wenig sagen, da ich nicht weiß,
welcher der Parameter von aussen hereingegeben wird -
bei @search dürfte es der Fall sein. Denen muß man besondere
Aufmerksamkeit schenken, was nur über den eigenen Code gesetzt
werden kann, ist weniger anfällig.Zudem solltest Du das "DISTINCT" in den SELECT Klasuel versuchen
zu elemenieren, das widerspricht sich mit ROWCOUNT.Aus Sicht der Wartbarkeit würde ich die Prozedur (intern) in mehrere
auftrennen, was die Abrufe der unterschiedlichen Sichten (vSeminarBuch,
vSeminarDetailGesamt) angeht. Langfristig blickt man erfahrungsgemöß
sonst nur noch schwer durch, was wo benötigt wird und es schleichen sich
Fehler (oder toter Code) ein.Gruß Elmar
-
Hallo Elmar,
Vielen Dank für die Info. Ich würde es ja gerne versuchen und meinen Bedingungen anpassen, das denke ich, schaffe ich. Die unterschiedlichen Sichten in mehrere Prozeduren auszulagern, macht eigentlich keinen Sinn. Das käme nur einem Kopieren der Prozedur gleich. Die Unterschieldichkeit liegt nur ein ein oder 2 Spaltennamen.
> wenn Du eine Verbindung offen hast, kannst Du zwei Aufrufe
> hintereinander absetzen und da die Paramter gleich sind, reicht
> eine (Sql)Command Instanz - wobei Du zuerst @TotalRows abfragen
> speichern solltest.Ich habe das in einer Instanz jetzt auch nicht geschafft, ich wüsste auch nicht mit welcher Syntax. Bei einer Insert-Anweisung kann ich einen Output-Parameter direkt dahinter selectieren, aber bei einer gespeicherten Prozedur? Auch die Google-Suche brachte nir nicht viel. Ich denke, mit @gettotalrows ist ja doch eine Unterschiedlichkeit da, welche ich jetzt auch nicht abzufragen wüsste.
>Bei weiteren Fragen dazu => ASP.NET Forum,
> wobei Du den derzeitigen Zugriff erläutern solltest - Stefan und Co.
> können dazu mehr sagen als ich (der nicht sonderlich webaffin ist).
Hmm, das möchte ich jetzt lieber nicht.
Ich finde es schon mehr als nett, dass Du Dich in die Prozedur reindenkst.
Letztendlich kann ich auch mit 2 Instanzen leben, es ich ja alles noch überschaulich.
Dim sda As New SqlDataAdapter()
Dim cmd As New SqlCommand("sp_seminarPaging2")
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("@PageNo", SqlDbType.Int).Value = PageNo
cmd.Parameters.AddWithValue("@sort", sort)
cmd.Parameters.AddWithValue("@search", search)
cmd.Parameters.Add("@ItemsPerPage", SqlDbType.Int).Value = ItemsPerPage
cmd.Connection = con
Dim sda1 As New SqlDataAdapter()
Dim cmd1 As New SqlCommand("sp_seminarPaging2")
cmd1.CommandType = CommandType.StoredProcedure
cmd1.Parameters.AddWithValue("@search", search)
cmd1.Parameters.AddWithValue("@gettotalRows", 1)
cmd1.Parameters.Add("@TotalRows", SqlDbType.Int).Direction = ParameterDirection.Output
cmd1.Connection = con
Try
con.Open()
sda.SelectCommand = cmd
sda1.SelectCommand = cmd1
sda1.Fill(dt)
sda.Fill(dt)
DataList1.DataSource = dt
DataList1.DataBind()
TotalRows = Convert.ToInt32(cmd1.Parameters("@TotalRows").Value)
Grundsätzlich läuft das so mit den 2 Instanzen. Ich werde dass jetzt mal Schritt für Schritt umbauen.
Aber ich hätte da noch eine Frage zu dem @search Parameter bzgl. meiner alten Prozedur.
Ich habe die Variable abgefragt
IF @search <> '%'
SET @search = '%' + ISNULL(@search, '') + '%'
dann in die Bedingung eingebaut
set @where = @where + '
(themen like @search or beschreibung like @search or kurztext like @search)
and dokstatus <=2'
Weiterhin der @parmalist hinzugefügt
und im EXEC auch ausgeben
SET @paramList = '@PageNo int,
@ItemsPerPage int,@search varchar(255)'
IF @debug = 1 PRINT @sql
EXEC sp_executesql
@sql,
@paramlist,
@search,
@PageNo,
@ItemsPerPage
Und trotzdem komme folgende Fehlermeldung:
Meldung 8114, Ebene 16, Status 5, Zeile 0
Fehler beim Konvertieren des varchar-Datentyps in int.
Meldung 137, Ebene 15, Status 2, Zeile 2
Die '@search'-Skalarvariable muss deklariert werden.
Was soll diese Meldung sagen? Ich konvertiere sie nicht und sie ist deklariert.
Liebe Grüße, die Luzie! -
Hallo Luzie,
wenn Du für das Hauptergebnis einen SqlDataAdapter verwendest, ist der Einsatz
von zwei SqlCommand Instanzen sinnvoller. Um den Ausgabeparameter zu erhalten,
benötigst Du keinen DataAdapter. Ein ExecuteNonQuery für das SqlCommmand
und abrufen des Parameters ("@TotalRows") danach reicht, siehe
Ändern von Daten mit gespeicherten Prozeduren (ADO.NET)
(das hier nichts geändert wird ist dafür ohne Belang).Was den Fehler bei der Parameterübergabe angeht:
Und die Meldung bezüglich der falschen Konvertierung resultiert daraus,
dass versucht wird, den @search-Parameter als @PageNo zu interpretieren.Alle bei sp_executesql verwendeten Parameter müssen in @paramlist
deklariert werden, und dann genau in der Reihenfolge aufgeführt werden.
Und bei Dir ist @search der Dritte (und nicht der 1.):SET @paramList = '@PageNo int, @ItemsPerPage int,@search varchar(255)'
Umgekehrt spielt es keine Rolle, ob der Parameter effektiv verwendet wird,
so dass Du auch mal einige "auf Vorrat" übergeben kannst.Gruß Elmar
- Als Antwort markiert Luzie Samstag, 12. Juni 2010 07:42
-
Hallo Elmar,
vielen Dank für die die Links. An executeNonQuery hätte ich jetzt nicht gedacht. Ich werde mal schauen.
Jetzt, wo Du es schreibst, ich bin vor ein paar Monaten schon mal über ein ähnliches Problem mit der Fehlermeldung gestolpert und bin daraufhin dann auch den Part mit der Reihenfolge gestoßen. Aber ich habe das total verdrängt oder vergessen. :) Wenn man es nicht immer macht.
Vielen Dank nochmal für die Mühe und die Ausdauer mit mir.
Ich bin so froh, dass ich ein Stück weiter bin und hoffe, dies bald als erledigt zu betrachten, bevor es mich umbringt. :)
Schönes, sonniges Wochenende wünsche ich.
Liebe Grüße, die Luzie!