Phänomen



  • Hi zusammen,

    ich hab hier echt schwere Kost 😉 also ich will folgendes machen. Ich hab Mitarbeiter die in verschiedenen Projekten Arbeiten, das will ich so darstellen.

    ANSID   proj1   proj2   proj3 
    emp1    100     300     NULL 
    Emp2    50      NULL    NULL
    

    da sich sowohl die Mitarbeiter als auch die Projekte in Anzahl und Titel ändern können, muss ich mir die Tabelle dynamisch erzeugen sobald ein Projekt oder Mitarbeiter hinzugefügt oder geändert wird. Soweit so gut. Das funktioniert einwandfrei. Jetzt kommt das eigentliche Problem. Wenn ich das mit meinem Windows Account mache bekomme ich die Tabelle wie erwartet zurück, wenn ich das mit dem WebUser mache, bekomme ich die Spaltennamen zurück aber keine Datensätze. Ich hab dem Webuser mittlerweile ALLE rechte gegeben um zu schauen ob es dann geht, aber selbst dann scheitert es. Ich verstehe auch nicht ganz wie es sein kann dass er offensichtlich das Create der Tabelle macht, dann aber das Select drauf nicht richtig bringt. Wenn ich im MS SQL Manager ein Select * auf die erzeugte Tabelle mach kommen auch nur die SpaltenNamen, wenn ich über den ObjectExplorer gehe und über den mit open Table die Tabelle öffne, dann zeigt er sie an.

    Hat einer von euch auch nur nen Ansatz von ner Idee was hier schief läuft? Ist das ein T-SQL Problem oder ein IDE Problem? Bzw. bescheisst die IDE?

    Bin für jede Idee dankbar.

    mfg polo



  • dein Tabellenlayout ist schonmal falsch...

    warum nicht einfach so:

    ID    Empl    Proj
    -------------------
    0     empl1   proj1
    1     empl1   proj2
    2     empl1   proj3
    3     empl2   proj3
    4     empl1   proj4
    .
    .
    .
    

    ?

    Dann sparst du dir schonmal dieses dynamische Erzeugen, da ein Datensatz genau eine Mitarbeiter-Projekt-Beziehung darstellt



  • Danke für den Tip, genau so sieht auch meine Verknüpfungstabelle zwischen Employees und Projects aus, jedoch will mein Chef eine Übersicht wie ich sie oben dargestellt hab. Und es funktioniert ja auch mit meinem Windows Account, nur mit nem SQl User nicht. Und das obwohl ich ihm alle Rechte eingeräumt hab.



  • Du brauchst 3 Tabellen gem. Normalisierung und besserem Design.

    1 Tabelle Mitabreiter mit ID
    2. Tabelle Projekte mit ID
    3. Tabelle ID der Mitarbeiter und ID der Projekte.

    Somit kannst DU nun abfragen welcher Mitarbeiter in welchem Projekt u.s.w. ist.
    Ein SQL kümmert sich erstmal nicht um die Darstellung. Der liefert nur Daten. Wie du sie dann Darstellst solltest DU dann im Code selbst machen.
    Bitte nicht erwarten das ein RDBMS die Daten gleich so liefert wie man sie auch darstellen möchte.

    Zu Deinem Rechteproblem.
    Wenn du eine Tabelle erzeugst muss Du auch die Rechte festlegen.
    Tabellen zu erzeugen ist aber schlechtes Design.



  • Ja genau diese 3 Tabellen hab ich ja auch fürs eigentliche Datenhandling. Nur will ich es eben anders darstellen, was per T-SQL deutlich einfacher ist, als im ASP .Net . Wenn ich mir die Daten auf dem Server schon fertig vorbereite, dann kann ich sie einfach in nem Grid darstellen, und ich muss das vereinen der Daten nur dann machen wenn sich Tatsächlich etwas ändert. Aber wie gesagt dass ist nicht das eigentliche Problem, das Problem ist, dass ich nicht weiss was der User noch für Rechte haben muss, damit er ein einfaches Select ausführen darf auf diese eben erzeugte Tabelle. Der Witz ist, er erzeugt die Tabelle einwandfrei und das Select drauf liefert dann aber keine Daten, nur die ZeilenKöpfe. Mit meinem WindowsAccount seh ich die Daten die der SQL User erstellt hab allerdings. Vielleicht verkompliziert das jetzt noch alles aber hier mal mein Code, das funktioniert:

    --==============================================================
    if exists (	select * from sysobjects
    		where id = object_id(N'[dbo].[uspCreateDynProjects]')
    		and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    	drop Procedure [dbo].[uspCreateDynProjects]
    GO
    Create Procedure [uspCreateDynProjects]
    as
    declare @Name varchar(250), @SQL varchar(4000)
    Set @SQL = ''
    	declare UserCursor CURSOR
    		for Select Name from dbo.Projects
    
    	open UserCursor
    	fetch UserCursor into @Name
    		while (@@fetch_status =0) Begin
    			set  @SQL = @SQL + ', [' + @Name + '] varchar(250)'
    			fetch UserCursor into @Name
    		end
    	close UserCursor
    	deallocate UserCursor
    Set @SQL = right(@SQL,len(@SQL) -1)
    
    Declare @FK varchar(1000)
    Set @FK = 'if exists (select * from dbo.sysobjects where id = object_id(''FK_EmployeeIn_dynProjects'') and OBJECTPROPERTY(id, ''IsForeignKey'') = 1) '
    Set @FK = @FK + 'Alter table _dynProjects drop Constraint FK_EmployeeIn_dynProjects '
    Set @FK = @FK + 'if exists (select * from dbo.sysobjects where id = object_id(''_dynProjects'') and OBJECTPROPERTY(id, ''IsUserTable'') = 1) '
    Set @FK = @FK + 'Drop table _dynProjects '
    
    Set @SQL = @FK + 'Create table _dynProjects(dynID int Identity(1,1) NOT FOR REPLICATION NOT NULL, Constraint UQ_dynProjects UNIQUE ([dynID]), Constraint PK_dynProjects Primary Key ([dynID]),[Employee] int NOT NULL, ' + @SQL + '); '
    Set @SQL = @SQL + 'Alter table _dynProjects add Constraint FK_EmployeeIn_dynProjects foreign key(Employee) references [Employees] (ID); '
    
    Exec (@SQL)
    GO
    --==============================================================
    

    Und das danach nicht:

    Select * from _dynProjects
    

    warum?



  • Ich hab den Fehler gefunden mein dummes Tool hat mir nicht angezeigt, dass ich zwei _dyProjects Tabellen hab. eine dbo. und eine SQLUser. Das insert ging immer in die dbo. und das Select hab ich auf die SQLUser. gemacht. Warum allerdings die IDE mir die andere Tabelle angezeigt hat verstehe ich echt nicht.

    So jetzt können wir diskutieren ob es gut oder nicht gut ist, für Visualisierungszwecke dynamische Tabellen zu erzeugen.

    Ich finde es gut! 😉



  • Polofreak schrieb:

    So jetzt können wir diskutieren ob es gut oder nicht gut ist, für Visualisierungszwecke dynamische Tabellen zu erzeugen.

    Wozu dieser Riesen-Aufwand? Warum nimmst Du keine temporäre Tabellen?
    http://www.sqlteam.com/article/temporary-tables



  • Ist schon deshlab nicht gut weil nicht 2 gleichzeitig arbeiten können.
    Der SQL-Server soll das machen was er kann.
    Daten liefern.
    Das Programm soll sie dann so darstellen wie es sein soll.
    Um dir aber eine Tabelle zu ersparen kannst Du auch eine View anlegen.



  • Wenn ich es richtig mitbekommen habe, will er eine Pivottabelle haben. Sollte bei unbekannter Spaltenanzahl schwierig sein, dieses mit einer View zu berechnen, wenn das RDBMS dies nicht extra unterstützt.
    Eine temporäre Tabelle ist nur in der Session sichtbar, die sie angelegt hat. Es kann für jede Session eine temporäre Tabelle mit denselben Namen erstellt werden. Diese Tabellen stören sich nicht.

    Unix-Tom schrieb:

    Der SQL-Server soll das machen was er kann.
    Daten liefern.

    Also ich habe es mir abgewöhnt in der Informatik in Dogmatiken zu denken. Ich würde es auch eher auf der Anwendungsebene lösen, aber wenn es aus irgendein Grund für ihn besser ist...



  • Er erstellt ja eine Tabelle und keine Temptabelle.
    Bei Datenbanken kann man auch nie eine Aussage machen: Dies ist das Vorgehen.
    Hier kommt es immer darauf an was man machen möchte.



  • Sorry war leider kurzfristig unterwegs, zurück zum Thema.

    Ja das alles in temporäre Tabellen zu machen ist durchaus sinnvoll hatte ich auch geplant, nur die ersten Versuche funktionierten noch nicht mit temp Tabellen ich muss noch ein wenig versuchen, denn ich erstelle ja die Splaten anhand eines Selects, Sprich ich muss Exec auf nen Text machen, dass ich meine Spalten die ich in ner varchar Variable hab hinzufügen kann. Wenn ich das hinbekomme dann kann ich es so machen. (Da sind halt noch paar nicht relevante Sachen drin.

    declare	@CostCentre varchar(4)
    set @CostCentre = '5040'
    
    -- Projects as Columns
    declare @Name varchar(250), @SQL varchar(4000), @Columns varchar(4000), @ColumnNames varchar(4000)
    Set @Columns = ''
    Set @ColumnNames = ''
    	declare UserCursor CURSOR
    		for Select Name from dbo.Projects
    
    	open UserCursor
    	fetch UserCursor into @Name
    		while (@@fetch_status =0) Begin
    			set  @Columns = @Columns + ', [' + @Name + '] varchar(250)'
    			set  @ColumnNames = @ColumnNames + ', [' + @Name + ']'
    			fetch UserCursor into @Name
    		end
    	close UserCursor
    	deallocate UserCursor
    Set @Columns = right(@Columns,len(@Columns) -1)
    Set @ColumnNames = right(@ColumnNames,len(@ColumnNames) -1)
    
    set @SQL = 'create table #temp(dynID int Identity(1,1), [Employee] varchar(50) NOT NULL, ' + @Columns + ' ,[Sum] int, [WorkLoad] float)'
    exec (@SQL)
    declare @Employee varchar(50)
    declare EmployeeCursor CURSOR
    	for Select ANSID from vwEmployees
    	open EmployeeCursor
    	fetch EmployeeCursor into @Employee
    		while (@@fetch_status =0) Begin
    			insert into #temp (Employee) Values (@Employee)
    			declare @Project varchar(250), @pBudget int
    			declare ProjectCursor CURSOR
    				for Select Projects.Name, PlanedPersonnelProjectBudget from EmployeesInProjects eIp join Projects on Projects.ID = eIp.Project  where Employee = (Select ID from Employees where ANSID  = @Employee)
    				open ProjectCursor
    				declare @BudgetSum int, @PlanedBudget float, @Workload float
    				Set @PlanedBudget = isNull((Select PlanedPersonnelBudget from vwEmployees where ANSID = @Employee),240000)
    				set @BudgetSum = 0
    				fetch ProjectCursor into @Project, @pBudget
    					while (@@fetch_status =0) Begin
    						declare @update varchar(250)
    						set @update = 'update #temp Set ['+ @Project + '] = ' + Convert(varchar(50),@pBudget) + ' where Employee = ''' + @Employee + ''''
    						print @update						
    						Exec(@update)
    
    						set @update = 'update #temp Set ['+ @Project + '] = ' + Convert(varchar(50),(Select PlanedProjectBudget from Projects where Name = @Project)) + ' where Employee = ''Total Budget'''
    						print @update						
    						Exec(@update)
    
    --						set @update = 'update #temp Set ['+ @Project + '] = ' + Convert(varchar(50),@pBudget) + ' where Employee = Total Budget'
    --						print @update						
    --						Exec(@update)
    
    						Set @BudgetSum = isNull(@BudgetSum,0) + isNull(@pBudget,0)
    						fetch ProjectCursor into @Project, @pBudget
    					end
    				close ProjectCursor
    			deallocate ProjectCursor
    
    			Set @Workload = round((@BudgetSum / (isNull(@PlanedBudget,240000))) * 100,2)
    			declare @test varchar(1000)
    			Set @test = 'update #temp Set [Sum] = '+ Convert(varchar(50),@BudgetSum) +', [WorkLoad] = ' + Convert(varchar(50),@Workload) + ' where Employee = ''' + @Employee + ''''
    			Exec(@test)
    		fetch EmployeeCursor into @Employee
    		end
    	close EmployeeCursor
    deallocate EmployeeCursor
    	declare @ColumnList nvarchar(4000)
    	Set @ColumnList = ''
    
    Set @SQL = 'Select ANSID, ' + @ColumnNames + ' from SQLKappa._dynProjects proj right join vwEmployees on vwEmployees.ANSID = Employee where vwEmployees.CostCentre = ' + Convert(varchar(50),@CostCentre) + ' or CostCentre = 0 order by ID,Nachname'
    Print @SQL
    Exec(@SQL)
    go
    

    Achja und ich finde es deutlich es direkt auf dem SQL Server zu machen wie in meiner Webapplikation.


Log in to reply