Laden...

Global Stored Procedure - Ungültiger Objektname xxx ?

Erstellt von ChrisProg vor 6 Jahren Letzter Beitrag vor 6 Jahren 4.318 Views
ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren
Global Stored Procedure - Ungültiger Objektname xxx ?

verwendetes Datenbanksystem: MS SQL-Server 2012

Hallo,

ich versuche gerade in die [master]-DB eine stored procedure zu schreiben, damit ich nicht in jeden Mandanten die stored procedure reinschreiben muß ...

Das funktioniert soweit auch ganz gut.

Nachdem die stored procedure erstellt wurde wird vom MS immer noch die ersten 7 Zeilen vorangestellt:

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[sp_meineprozedur]    Script Date: 24.10.2017 16:20:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[sp_meineprozedur] (@nr int) 
 as  
 begin
  print (db_name())
  
  select * from meinetabelle
end;

Ich rufe die prozedur mit

DECLARE @DatabaseName sysname = 'meineDB'; 
declare @sql nvarchar(255);
SET @SQL = N'USE ' + QUOTENAME(@DatabaseName) + '; exec sp_meineprozedur 27;' 
print (@sql);
exec (@sql)

Anhand des Befehls "print (db_name())" kann ich sehen, das die richtige DB ausgewählt wurde;
trotzdem erhalte ich immer die Fehlermeldung: > Fehlermeldung:

"Ungültiger Objektname 'meinetabelle'.

Was muß ich noch beachten / mache ich noch falsch ???

MfG ChrisProg

T
461 Beiträge seit 2013
vor 6 Jahren

Also soweit ich mich erinnere, muß man die Datenbank (Schema) und Tabelle angeben, also so ca:


select * from [Database].[Schema].[meinetabelle]

denn dann findet er genau hin...

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

16.835 Beiträge seit 2008
vor 6 Jahren

Kurzer Hinweis: euch ist hoffentlich gewusst, dass so ein Konstrukt sowohl die Skalierung wie auch die Wartbarkeit von Anwendungen - besonders Mehrmandantenfähigkeit - extrem negativ beeinflusst und anfällig für Probleme macht?
Sowas solltet ihr für die Zukunft absolut beachten!

Das Injezieren von Datenbanken als Parameter ist absolut nicht zu empfehlen; sogar als Warnung zu sehen.
Willst Du das wirklich, was wirklich nicht zu empfehlen ist, dann geht das nicht über Parameter, sondern nur über Dynamic SQL.
Dynamic SQL ist aber anfällig für SQL Injection und auch bzgl. der ausführenden Rechte problematisch.

Willst Du eine fixe Tabelle, dann brauchst Du den DBO Name.
Edit: hier war ThomasE. schneller.

Ich persönlich würde ganz die Finger von Stored Procs lassen, weil euch das extrem Abhängig von einer Datenbanktechnologie macht und - eben für die Zukunft und wachsende Mandanten - sehr problematisch, aufwändig und teuer in Sachen Skalierbarkeit ist.
Deswegen findet man in Cloud-Produkten auch nur - wenn überhaupt - unterstützung von Stored Procs: sie sind einfach nicht so wirklich skalierbar.
Skalierbarkeit ist aber natürlich auch für On Prem wichtig.
Soviel nur als Hinweis.

T
461 Beiträge seit 2013
vor 6 Jahren

Was willst du am Ende überhaupt damit erreichen? Von wo aus soll was Selektiert werden? (Vielleicht) können wir eine alternative Lösung anbieten.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Hallo,

das war natürlich nur ein kleines Beispiel.

Konkret geht es z.B. um über 400 Zeilen Code mit deren Hilfe ich über (fast) alle Tabellen einer DB z.B. die aktuellen Bestände / Kosten eines Artikels ermittle ...

Als Ergebnis bekomme ich dann eine Tabelle / ein Ergebnis zurück.

Der Code ist dabei immer bis auf z.B. die Artikel-Nr identisch.

Ich habe bisher diese Zeilen in einem SQL-Command direkt gesendet (funktionierte einwandfrei ...) - nun wollte ich (um das ganze zu optimieren - Zeitersparnis ?) das in eine stored procedure packen - da wir mehrere Mandanten haben und ich die stored procedure nicht in jeden Mandanten eintragen will, kam ich halt auf den Gedanken diese stored procedures global zu speichern.

@Abt: ich dachte der Befehl QUOTENAME wäre extra dafür da, um das Injezieren zu verhindern ?

MfG ChrisProg

T
461 Beiträge seit 2013
vor 6 Jahren

Hallo,

Konkret geht es z.B. um über 400 Zeilen Code

meinst du im Grunde SQL-Skript?

Somit wäre:

(Der Code) Das Skript ist dabei immer bis auf z.B. die Artikel-Nr identisch.

Wie stellst du dieses Skript zusammen?
Wieviele Tabellen hat ca. so eine DB?

Ich habe bisher diese Zeilen in einem SQL-Command direkt gesendet (funktionierte einwandfrei ...)

Wie Abt schon gepredigt hatte 😁 wird dadurch die Wartbarkeit und Skalierung negativ beeinflußt. In dem Fall ist diese Art von Optimierung eher nicht zu empfehlen.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Hallo,

meinst du im Grunde SQL-Skript?

ja ...

Wie stellst du dieses Skript zusammen?

Ich erstelle das Script (mehrere Tabellen, die über union all verknüpft ausgelesen und das Ergebnis in eine temp-Table gespeichert und anschließend weiterverarbeitet wird) immer erst im Management Studio; danach kopiere ich es in meine c#-Anwendung (als sql-command...)

Wie viele Tabellen hat ca. so eine DB?

über 70 (von denen aber für die Abfrage "nur" ca. 30 für die Abfragen gebraucht werden) ...

Wie Abt schon gepredigt hatte wird dadurch die Wartbarkeit und Skalierung negativ beeinflusst. In dem Fall ist diese Art von Optimierung eher nicht zu empfehlen.

Wieso beeinflusse ich die Skalierbarkeit des SQL-Servers - dieses Script () muss so ausgeführt werden - und die Skalierbarkeit hat doch eher was mit der hardwareseitigen Optimierung zu tun, oder ?

Ich war halt nur der Meinung das ich mit Hilfe einer stored procedure Zeit sparen kann, da ich ja das Script nicht jedes mal wieder an den SQL-Server schicken muss ...
So ein Script kann schon mal fast 1 s dauern (wenn es extrem viele Buchungen für diesen Artikel gibt) - das ist bei einer einzelnen Abfrage noch kein Problem; nur wenn ich Statistiken erstellen soll ...

MfG ChrisProg

16.835 Beiträge seit 2008
vor 6 Jahren

Du beeinflusst damit die Skalierbarkeit, weil Du einen Server nicht unendlich vertikal (scale up) skalieren kannst.
Du musst irgendwann in die Breite gehen und horizontal skalieren (scale out).
Die Zeiten von "ich hab nur einen Datenbankserver für alles" sind vorbei; wie gewährleistest Du Performance? Wie Traffic Spitzen? Wie Redudanz?
Das alles geht mit nur einem Datenbankserver nicht.

Die Wartbarkeit beeinflusst Du negativ, weil Du alle Mandanten damit eindämmst.
Wenn Du die Anwendung aktualisierst, dann muss das für alle Mandanten auf ein mal passieren; das macht man normalerweise nicht.
a) weil Mandanten Wartungsfenster haben wollen und b) weil Du bei einer auftretenden Problematik sofort alles down setzt statt dass nur Teilbereiche betroffen sind.

Um Zeiten zu sparen und die Performance zu verbessern gibt es andere Wege statt die Datenbank als Logikschicht zu missbrauchen 😉

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Hallo,

Um Zeiten zu sparen und die Performance zu verbessern gibt es andere Wege statt die Datenbank als Logikschicht zu missbrauchen 😉

Und was könntest Du mir da für WindowsForms empfehlen ?

MfG ChrisPorg

16.835 Beiträge seit 2008
vor 6 Jahren

Windows Forms hat damit ja recht wenig zutun!?

Letzten Endes geht es darum, dass Du die Anwendungslogik in der Anwendung hälst, und nicht in der Datenbank. Da gehört sie nicht hin, weil sie hier nur schwer wartbar und auch kaum testbar ist; zudem die hohe Abhängigkeit einer Technologie.

Die Datenbank-Operationen gehören in einer [Artikel] Drei-Schichten-Architektur in die Schicht der Datenbank.
Wie Du nun mit der Datenbank kommunizierst: hier führen viele Wege nach Rom.
Mein Favourite ist hier Dapper, ein Micro-ORM, der kaum Performance-Verlust in Sachen Type-mapping hat und sehr gut mit nativem SQL konkurrieren kann.

Die Anwendungslogik ist dann im Rahmen des Service Layers dann für die Mandantenfähigkeit verantwortlich, wobei jeder Mandant physikalisch seine eigene Datenbank bekommt, damit er autark arbeiten kann, ein gewisser physikalischer Sicherheitsaskept gewährleistet werden kann und eben jeder Mandant theoretisch einzeln wartbar ist.

Lektüre auf Anhieb hab ich jetzt keine parat; jedenfalls keine öffentlich zugängliche - sorry.
Mandantenfähige Systeme sind aber durchaus gebräuchlich; hier gibt es sicherlich einige Treffer bei einer entsprechend tiefen Recherche; oder man muss sich Knowhow für 1-2 Tage ins Haus holen.
Dafür gibts ja solche Leute.

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Hallo,

@Abt: danke für deine Ausführungen...

Aber mein eigentliches (vielleicht auch nur gedankliches) Problem löst das nicht.

Das mit dem Drei-Schichten-Modell ist einleuchtend u. auch mit Sicherheit in größeren Projekten und im Team sinnvoll.

Noch mal zum Verständnis:

Ich habe, sagen wir mal 200 Artikel, von denen ich nacheinander die aktuelle Menge und die aktuellen Kosten/ Gewinne ermitteln möchte ...

Nacheinander alleine schon deshalb, um dem Kunden in der Statusleiste anzuzeigen, bei welchen DS / Artikel das Programm gerade ist.

Wie gesagt, das Script ist mehr als 400 Zeilen groß und es ändert sich jedes mal nur die Artikel-Nr als Filter.

Meine Logik sagt mir, das es auch eine gewisse Zeit braucht, bis ich das Script per SqlCommand an die DB übergeben habe, der Interpreter den Code in eine temporäre Prozedur umgewandelt (so habe ich es verstanden ...) und ausgeführt hat.

Nun wollte ich mir die Zeit für das 200-malige übertragen des Codes und das ebenfalls 200-malige erstellen einer temporären Prozedur sparen - deshalb der Gedanke einer "stored procedure", bei der ich ja nur noch den Parameter artikel übergeben muß.

Alleine schon, wenn diese beiden Möglichkeiten im Management Studio ausprobiere merke ich einen Zeitunterschied.

Für einen einfachen "Select ..." würde ich niemals auf die Idee einer stored procedure kommen...

Mir ist natürlich klar, das auch diese stored procedure dann gepflegt werden muss - ich plante die entsprechenden stored procedures per drop beim beginn der Programmausführung zu löschen und dann einmalig neu zu schreiben - wobei mir jetzt beim schreiben dieser Zeilen klar wird, das auch das nicht sauber funktionieren kann in einer Multi-User-Umgebung 🤔 --> bleibt dann doch bei einer temporären Prozedur 🙁

MfG ChrisProg

16.835 Beiträge seit 2008
vor 6 Jahren

Wenn Du wirklich das Übertragen von 17 Byte Deines Queries einsparen willst, dann nennt sich das Mikro-Optimierung.
Dazu gibt den Quote von https://en.wikiquote.org/wiki/Donald_Knuth: premature optimization is the root of all evil (or at least most of it) in programming

Du baust hier eine "Optimierung", die dermaßen viele Nachteile hat, dass Du damit mehr verbaust als erreichst.
Wenn das tatsächlich Dein einziges Bottleneck ist, die Übertragung eines Queries, dann Respekt.

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Hallo

Wenn Du wirklich das Übertragen von 17 Byte Deines Queries einsparen willst, dann nennt sich das Mikro-Optimierung.

Es geht mir nicht um 17 Byte ( wie kommst Du auf diese Zahl ?) sondern um die Zeit die der SQL-Server offensichtlich jedes mal braucht um das Script zu generieren ...

Wenn das tatsächlich Dein einziges Bottleneck ist, die Übertragung eines Queries, dann Respekt.

Das ist mit Sicherheit nicht mein einziges Problem; ich habe gerade erst mit dem Projekt begonnen u. will halt von Anfang an versuchen so viel Zeit zu optimieren wie möglich.

Denn bis jetzt finde ich c# + MS SQL ist nicht schneller als VFP 8o - oder (was wohl wahrscheinlicher ist) ich habe noch nicht die richtigen Wege / Methoden gefunden ... X(

MfG ChrisProg

16.835 Beiträge seit 2008
vor 6 Jahren

17 Byte hab ich einfach mal in den Raum geworfen, um die Gewichtung einer solchen Einsparung zu zeigen.
Compiled Queries und Execution Plan Caching kann auch ADO.NET (als Providerteil des SQL Servers).
Dafür braucht man keinen komplexes, mutierendes Stored Proc.

Es ist aber Tatsache, dass alte SQL Server Versionen wirklich nur Stored Procs und dessen Execution Plan cachen konnten.
Neue SQL Server Versionen können jede Art von Statement (adhoc / sproc) cachen und diese einfach parametrisieren.
Der Performance-Vorteil von Stored Procs gibt es so gar nicht mehr.

Performance hat nicht unbedingt was mit der Sprache zutun, sondern auch bzw. maßgeblich, wie man programmiert.
Zudem hast Du nicht wirklich viel gewonnen, wenn Du 0,25% (wieder fiktiv) an Performance gewinnst aber 90% an Wartbarkeit und Zukunft verlierst.

Letzten Endes musst Du aber entscheiden, wie der Weg für Dich und Dein Projekt weiter geht.
Wir sehen das hier alles ja nur aus der Ferne und können Dir allgemeine Ratschläge geben.

Wenn Du sagst, dass die Stored Procs so nicht wirtschaftlich migriert werden können, dann ist es eben so.

u. will halt von Anfang an versuchen so viel Zeit zu optimieren wie möglich

Genau das nennt man aber premature optimization is the root of all evil (or at least most of it) in programming

T
2.224 Beiträge seit 2008
vor 6 Jahren

Die Frage die ich mir stelle ist, warum gibt es so viele Tabellen bei dir?
Sind dort die Daten auf Tabellen Ebene dermaßen stark gerennt, dass du 30 Tabellen joinen musst?

Über welche Leitung geht dein Skript?
Bzw. warum ein Skript?
Warum schickst du deinen Code nicht einfach direkt ohne Umwege über Funktionen/Prozeduren?

Die Argumente gegen eine Funktion o.ä. im DB Server wurden ja schon genannt.
Für die Dynamik bei der Artikelnummer brauchst du Sql Parameter, gibt dazu Infos im Netz/Dokus etc.

C# mit MS SQL ist, wenn man eine saubere Architektur in der Anwendung und DB hat, genauso schnell wie alle anderen Relationalen DBs.
Wir setzen bei uns primär noch den MS SQL Server ein und haben kaum weniger Leistung als PostgreSql oder MySQL.

Es hängt immer von der Hardware und Software Konfiguration ab.
Und natürlich von der Software, die auf diese DBs zugreift.

VFP scheint ja seit 2007 keine Updates mehr bekommen zu haben, ist also kein gängier Vergleich zu sein.
Der SQL Server hat für solche Anwendungen genug Dampf, setzen für eine Flottenlösung mit Mandanten sowie für eine Aussendienstlösung für größere Kunden ein.
Diese Verwaltungen Datenmengen für ihre Daten teilweise im Millionen Einträge bereich ohne lange Ladezeiten(wenige Millisekunden) durch saubere Optimierung der Software.

Wenn du, wie Abt schon schreibt, solche Optimierungen machen musst, ist deine Architektur nett gesagt ungünstig aufgebaut.

Aber hier würde ich gerne wissen, warum du soviele Tabellen brauchst.
Klingt für mich nach einem alten Konzept in dem wir mal für jeden Mandanten eigene Tabellen mit der MandantenNr. als Prefix hatten.
Am ende hatten wir eine Datenbank mit mehr als Tausend Tabellen, die weder Wartungsfreundlich geschweige den gut zu sichern war.

Hier kann man die Daten auch innerhalb einer Tabelle durch saubere Relationen trennen und die Anzahl der Tabellen gering halten.

Aber die Argumente würde ich gerne kennen, damit ggf. ein besserer Ansatz gewählt werden kann.
Ebenfalls wäre hier eine einfache Lösung wie eine Ergebnis Tabelle und eine Auswertung in einem Task sinnvoller als ein fettes SQL Skript, was irgendwann keine mehr versteht oder warten kann.

Nachtrag:
@Abt
Ist richtig.
Wie geschrieben, hängt die Performance maßgelich von der Umsetzung in der eigenen Software ab.
Aus meiner Erfahrung heraus, würde ich auch keine Logik in der DB ablegen.
Könnten wir uns auch kaum leisten können, da wir gerade mit neuen Projekten teilweise auf PostgreSql umstellen wollen.
Diese dann wieder zurück migrieren oder für einen Kunden ggf. portieren, wäre dann eine Katastrophe.
So müssen wir unserem OR Mapper nur von einer auf die andere Datenbak umstellen, der Rest läuft über den Code.

Aber wie geschrieben, sauberer Code + ordentliche DB Struktur, dann hat man auch keine Performance probleme.
Mikrooptimierungen kann man sich sparen, erst wenn Code zu lange läuft, zu viel RAM frisst oder andere Engpässe eintreten, kann man erst mit optimieren anfangen.
Ansonsten verbrennt man Zeit und gewinnt kaum Performance.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
1.090 Beiträge seit 2011
vor 6 Jahren

@ChrisProg
Du brauchst doch auch in Zukunft Update Skrips für die einzelnen Datenbanken. Mit den Mechanismus solltest du auch die Stored Procedure ausliefern. Falls du sie überhaupt noch verwenden willst.

Zur Preformance schau dir mal den Beitrag an: stackoverflow:Why Stored Procedure is faster than Query

Und wenn die die Stored Procedure in die Master DB schreibst, braucht deine Software zu mindestens die Rechte diese Stored Procedure auf der Master DB aus zuführen. Irgendwie halte ich das für keine gute Idee.

Dann mal eine andere Frage du redest hier von einem Mehr Mandanten System, das klingt jetzt erst mal für mich nicht so als ob es sich auf ein Lokales Netzwerk beziehen würde?

Da du grade erst mit dem Projekt angefangen hast. Mach ziehe dir Zwischen Client und DB einen Service Layer. Das bietet mehr Sicherheit und Skaliere auch deutlich Besser. Fall du in Zukunft feststellen solltest, das du Performance Probleme hast, hast du einfach mehr Möglichkeiten.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

P
1.090 Beiträge seit 2011
vor 6 Jahren

@T-Virus
Wenn man in der 3. Normalform ist, kommen schon recht schnell viele Tabellen zusammen. Da ist es aber manchmal sinnvoll aus Performance gründen nicht die 3. Normalform anzunehmen.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

T
2.224 Beiträge seit 2008
vor 6 Jahren

@Palin
Ich würde sogar soweit wie Abt gehen und komplett von Stored Procedures abraten.
Hatte bisher keinen Fall, in dem ich einen Vorteil hatte eine zu verwenden.

Dein Hiwneis zu Client und Service Layer ist natürlich auch ein guter Einwurf.
Hier fehlt auch die Info ob es sowas schon gibt oder direkt jeder Client auf die DB zugreift.
Das Thema hatten wir erst vor kurzem, da passt es auch gut dies nochmal zu erwähnen.

Die dritte Normalform kann natürlich ordentlich Tabellen produzieren, was auch gewollt ist wenn man die Daten richtige aufteilt.
Leider erwischen wir uns zu häufg dabei, diese wegen bestehenden Tabellen gerne mal wegzulassen und die Daten entgegen dem Konzept in eine neue Spalte zu hauen.
In unserem neuen Projekt haben wir dies aber gleich von Anfang an sauber umgesetzt!

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

P
1.090 Beiträge seit 2011
vor 6 Jahren

@T-Virus
War auch so gemeint den Service Layer zu Verwenden und dafür auf die Stored Procedure zu verzichten.

Ich bin sowieso dafür soweit es geht bei dem SQL Server nur Vanilla SQL zu verwenden.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 6 Jahren

Es ist aber Tatsache, dass alte SQL Server Versionen wirklich nur Stored Procs und dessen Execution Plan cachen konnten.
Neue SQL Server Versionen können jede Art von Statement (adhoc / sproc) cachen und diese einfach parametrisieren.
Der Performance-Vorteil von Stored Procs gibt es so gar nicht mehr.

Zur Preformance schau dir mal den Beitrag an:
>

Nach diesem Artikel / Abt´s Beschreibung würde es ja wenig Sinn machen eine stored procedure zu verwenden, wenn SQL die vorherigen Scripts im Speicher behält ...

Nur muss man wahrscheinlich darauf achten, das man dann weiterhin mit dem Parameter ("artikel" in meinem Beispiel) arbeitet, damit SQL das Script als bereits vorhanden erkennt.

Danke allen für die Inputs, ich werde alles noch mal überdenken ... 🙂

MfG ChrisProg