Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
RWSmith
Starting Member
4 Posts |
Posted - 2011-08-08 : 13:12:16
|
| Okay, I am new.Using .NET 2.0 and SQL Server 2005, this may actually be more of a vb question than a sql question, not sure. My problem is working with the dataset.I have a vb.net function that needs to find any unit id from a unit table associated with a building. Need to grab top unit id from dataset, delete all other unit ids in that table and use top unit id to set all other records in four different tables to the top unit id. I may be going about this all wrong. Any help or suggestions would be appreciated.So far it looks like this.... Protected Sub GetAssociatedUnits() Dim sql As String sql = "" & _ "SELECT Units.UnitID FROM Units WHERE BuildingID = '" & _buildingID & "') " Dim dataSet As New DataSet If (Database.GetDataSet(sql, dataSet) = False) Me.Error_Label.Text += Database.DbError & "<br>" Return End If Dim rowCount As Integer rowCount = dataSet.Tables(0).Rows.Count If (rowCount > 1) _tempUnitID = Convert.ToInt32("SELECT TOP UnitID FROM Units WHERE BuildingID = '" & _buildingID & "') " ) 'loop through result set and update any other tables with that unit id then delete all but top unit id from unit table FOR Each row As DataRow In dataSet.Tables(0).Rows _tempUnitID1 = CType(dataSet.Tables(0).Rows.Item("UnitID"),Int32) "UPDATE Meetings Set UnitID = '" & _tempUnitID & "' WHERE UnitID = '" & _tempUnitID1 & "')" & _ "UPDATE DocumentAssociations Set UnitID = '" & _tempUnitID & "' WHERE UnitID = '" & _tempUnitID1 & "') " & _ "UPDATE UnitProducts Set UnitID = '" & _tempUnitID & "' WHERE UnitID = '" & _tempUnitID1 & "') " & _ "UPDATE UnitContacts Set UnitID = '" & _tempUnitID & "' WHERE UnitID = '" & _tempUnitID1 & "') " "DELETE * FROM Units WHERE UnitID = '" &_tempUnitID1 & "') " NEXT End If End Sub |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-08-08 : 15:44:21
|
It is much safer and easier to do this in a stored procedure. It is safer because you can ensure the atomicity of the operations (i.e., either all of the operations will succeed together, or they will all fail together, thus ensuring data integrity). It is also safer because it avoids the "ad-hoc" query which can be less efficient, may even be prone to SQL injection attacks.Easier because, as you can see, there are fewer lines of code, and it looks more readable (at least to me )I don't completely understand your business logic, or I may have misunderstood them. So this is only and example, please look through it and understand and modify to your requirements, and test in a dev environment if you do choose to use this approach.Once you have the stored proc, in .Net 2.0, you can connect to the database using ADO.Net; you would pass in one parameter to the stored proc, namely the building id.CREATE PROCEDURE dbo.FixupUnitIds @building_id INTAS BEGIN TRY -- exception handling. BEGIN TRAN -- do it in a transaction, so all of the operations will succeed or fail together. DECLARE @highest_unit_id INT; -- find the highest unit id SELECT @highest_unit_id = MAX(UnitId) FROM Units WHERE BuildingId = @building_id; -- update the four tables UPDATE Meetings SET UnitID = @highest_unit_id WHERE BuildingId = @building_id; UPDATE DocumentAssociations SET UnitID = @highest_unit_id WHERE BuildingId = @building_id; UPDATE UnitProducts SET UnitID = @highest_unit_id WHERE BuildingId = @building_id; UPDATE UnitContacts SET UnitID = @highest_unit_id WHERE BuildingId = @building_id; -- delete all except the highest unit id DELETE FROM Units WHERE UnitId <> @highest_unit_id AND BuildingId = @building_id; COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN; SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage END CATCHGO |
 |
|
|
jcelko
Esteemed SQL Purist
547 Posts |
Posted - 2011-08-08 : 23:49:19
|
| Every SQL forum or newsgroup expects that you will post DDL, sample data and clear specifications which might might include output. This is explained in the FAQ section. We can not read minds; what would we need to know to do your job for you? Tables must have keys and should have DRI, constraints, and all the basic features of a schema. You should know use ISO-8601 Standards for temporal data, avoid needless dialect, basic data modeling and use ISO-11179 Standards for data element names. Please tell us if you can change the DDL. >> I have a vb.net function that needs to find any unit id from a unit table associated with a building. Need to grab top unit id from dataset, delete all other unit ids in that table and use top unit id to SET all other records [aic: rows are not records] in four different tables to the top unit id. I may be going about this all wrong <<Yes, this all wrong. SQL is a SET-oriented language. Writing a loop is like cannibalism to SQL programmers; you might do it at home, but not where people can see you.You are writing a “scratch tape” as if you were still in COBOL or Flow-matic with magnetic tape files. The same unit_nbr physically repeated in so many places is a sign of more “mag tape in SQL” thinking. Since you violated basic Netiquette we have no way of re-writing the DDL for you. Let me do your job: CREATE TABLE Units(bldg_nbr VARCHAR(5) NOT NULL, unit_nbr VARCHAR(5) NOT NULL, PRIMARY KEY (bldg_nbr, unit_nbr_max),..); You can find the set of max units and put it in a VIEW; the VIEW is always current.CREATE VIEW Bldg_Unit_Max(bldg_nbr, unit_nbr_max)ASSELECT bldg_nbr, MAX(unit_nbr) AS unit_nbr_max FROM Units GROUP BY bldg_nbr; Assume each of these other tables has a building number that matches to the VIEW, we can write a colleciton of VIEWs CREATE VIEW Meetings_Unit_Max (..)ASSELECT M.*, MAX(U.unit_nbr) AS unit_nbr_max FROM Meetings AS M, Units AS U;The VIEWs will always be current. But if you insist on a mag tape file, you can use a VIEW to update your other tables. BEGINUPDATE Meetings SET unit_nbr = (SELECT unit_nbr_max FROM Bldg_Unit_Max AS BUM WHERE BUM.bldg_nbr = Meetings.bldg_nbr);UPDATE DocumentAssociation SET unit_nbr = (SELECT unit_nbr_max FROM Bldg_Unit_Max AS BUM WHERE BUM.bldg_nbr = DocumentAssociation.bldg_nbr);UPDATE UnitProducts SET unit_nbr = (SELECT unit_nbr_max FROM Bldg_Unit_Max AS BUM WHERE BUM.bldg_nbr = UnitProducts.bldg_nbr);UPDATE UnitContacts SET unit_nbr = (SELECT unit_nbr_max FROM Bldg_Unit_Max AS BUM WHERE BUM.bldg_nbr = UnitContacts.bldg_nbr);END;--CELKO--Books in Celko Series for Morgan-Kaufmann PublishingAnalytics and OLAP in SQLData and Databases: Concepts in Practice Data, Measurements and Standards in SQLSQL for SmartiesSQL Programming Style SQL Puzzles and Answers Thinking in SetsTrees and Hierarchies in SQL |
 |
|
|
RWSmith
Starting Member
4 Posts |
Posted - 2011-08-09 : 14:42:51
|
| Apologies I did not practice proper netiquette! Sorry, 60 year old man here, so facing a learning curve.sunitabeck Thank you so much for your suggestion of a stored procedure. I had not thought of that.jcelko, thanks for you help as well, you obviously know your stuff.Yes each table has a primary key and no building id is only in the unit table. This is me trying to fix an old .NET 2.0 application that ishaving issues with users wanting to do things the application was not originally designed to do. So, to better explain my issue, users often create buildingsas mutli-family buildings and add in multiple units before realizing that the building is a single family house. They then want it to magicallyconvert to a single family building with only one unit. So I am trying to behind the scenes take all of the existing units and any associated documents and roll them all up under one unit. The loop was my idea to try to get all of the possible units with the building id and then grab thetop or max one and then use that id to update the other unit ids in the other corresponding tables. There can be up to several hundred unit ids for the building in the units table. Thus the loop. Problem is the code needs to go through units one by one and grab any documents or meetings and then update those records with the one unit id(max). The other tables- meetings, documents and unit contacts each have a unitid field and primary keys of meetingid, documentid and contactid, respectively. If this helps anyone understand my problem better, please offer suggestions. I will attempt to write this in a stored procedure utilizing the view idea jcelko offered rather than looping through an array of unit id results and see what happens. Running out to buy a SQL book, maybe that will help, since I am in way over my head.Thanks again for your help, patience and suggestions. |
 |
|
|
RWSmith
Starting Member
4 Posts |
Posted - 2011-08-10 : 14:22:52
|
| Okay, with your suggestions and code (thank you)I have created a stored procedure but when I parse to check the code I am getting lots of error messages I am not understanding. I changed some requirements since the most important piece is the documents associated with the unit. Here is what I have so far...CREATE PROCEDURE dbo.sp_ConvertMFtoSF @bldg_id INT AS BEGIN TRY BEGIN TRAN CREATE VIEW dbo.UnitBuildingView AS SELECT UnitID, BuildingID FROM dbo.Units WHERE BuildingID = @bldg_id-- GO DECLARE @first_unit_id INT; -- find the oldest unit id SELECT @first_unit_id = MIN(UnitId) FROM UnitBuildingView; -- update the tables UPDATE [dbo].[DocumentAssociations] SET UnitID = @first_unit_id WHERE BuildingId = @bldg_id; UPDATE [dbo].[Buildings] SET BuildingUseType = 'SingleFamily', NumberUniits = '1' WHERE BuildingId = @bldg_id; -- delete all except the highest unit id DELETE FROM [dbo].[Units] WHERE UnitId <> @first_unit_id AND BuildingId = @bldg_id; COMMIT TRAN END TRY-- BEGIN CATCH-- ROLLBACK TRAN;-- SELECT-- ERROR_NUMBER() AS ErrorNumber,-- ERROR_SEVERITY() AS ErrorSeverity,-- ERROR_STATE() AS ErrorState,-- ERROR_PROCEDURE() AS ErrorProcedure,-- ERROR_LINE() AS ErrorLine,-- ERROR_MESSAGE() AS ErrorMessage-- END CATCHGOthese are the error messages....Msg 156, Level 15, State 1, Procedure sp_ConvertMFtoSF, Line 11Incorrect syntax near the keyword 'VIEW'.Msg 102, Level 15, State 1, Procedure sp_ConvertMFtoSF, Line 30Incorrect syntax near 'TRY'.The syntax near view and try?I have searched through a SQL book I purchased and have looked at other stored procedures with views online and do not see the syntax error.Did I need to move the view to be above the transaction start?Any suggestions are greatly appreciated.Thanks again for all of your help!! |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-08-10 : 15:43:11
|
Change it like shown below. I think you may have copied code which somehow included a view definition nested inside your stored procedure definition. Run it in a test environment before you do anything for real. Once you create the stored procedure using this code, run it like this:exec dbo.sp_ConvertMFtoSF 3422 -- assuming 3422 is the building id. If it does not do exactly what you need and you want to make changes, you can alter the stored procedure or drop and recreate it. You can drop a stored procedure using "DROP PROCEDURE dbo.sp_ConvertMFtoSF".Here is the revised version of the stored proc.CREATE PROCEDURE dbo.sp_ConvertMFtoSF @bldg_id INTASBEGIN TRY BEGIN TRAN SELECT UnitID, BuildingID FROM dbo.Units WHERE BuildingID = @bldg_id -- GO DECLARE @first_unit_id INT; -- find the oldest unit id SELECT @first_unit_id = MIN(UnitId) FROM UnitBuildingView; -- update the tables UPDATE [dbo].[DocumentAssociations] SET UnitID = @first_unit_id WHERE BuildingId = @bldg_id; UPDATE [dbo].[Buildings] SET BuildingUseType = 'SingleFamily', NumberUniits = '1' WHERE BuildingId = @bldg_id; -- delete all except the highest unit id DELETE FROM [dbo].[Units] WHERE UnitId <> @first_unit_id AND BuildingId = @bldg_id; COMMIT TRANEND TRYBEGIN CATCH ROLLBACK TRAN; SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessageEND CATCHGO |
 |
|
|
RWSmith
Starting Member
4 Posts |
Posted - 2011-08-10 : 17:10:37
|
| Sunitabeck,Thank you so much for your help!! Unlike Mr.Celko with all his books to sell, you seem to be just trying to help people. Kudos to you and I pray many blessings come your way. I was creating the view as Mr.Celko suggested in the stored procedure to hold the data in while I worked with it. But after reading your post I had a brainstorm and made separate calls. One to create the UnitBuildingView on the fly, then a modified version of the stored procedure, then a third call to drop the view. Works great!!And for Mr.Celko, obviously I said I was new. Just began learning SQL this week to fix an issue for my small one man shop property renovation business, still have no idea what a DDL is? ISO-8601 Standards? What the hell is that? Do my job for me? You are a gem! Why even post a reply in the new to sql section if you have such an attitude about it? Your rudeness will come back to you one day sir. I pray that the universe blesses you anyway! Sunitabeck Thanks again!! |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-08-11 : 09:28:37
|
| Creating a view on the fly for a one-time use and dropping it after the use is not a usual practice - Because creating the views and dropping them are expensive operations; Also views are sort of like tables (they are virtual tables) which, once created is available for you to use any time, just like tables.Even though creating and dropping the views each time makes me a little queasy, if your code is working as you want it to I guess it is okay to leave well-enough alone. But, if you have performance issues or if it is not doing the tasks as you expect, post the scripts for the stored procedure and the views. (In object explorer in SQL Server Management studio you can right click on the stored proc or table and select script as -> Create to -> New Query editor window to script the stored proc/view). |
 |
|
|
|
|
|
|
|