Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Database & SysAdmin
  3. Database
  4. Best way to get PK value of newly created record

Best way to get PK value of newly created record

Scheduled Pinned Locked Moved Database
databasesql-serversysadmin
11 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Aaron Hartley
    wrote on last edited by
    #1

    I have a VB program that uses SQL Server as a database. One of the tables has a primary key, a serial number, that is inserted as part of the insert statement. The VB program determines the correct serial just prior to creating and executing the insert statement. The serial number not an incrementing value but is an aggregate of several pieces of information. Since I have copies of the same VB program running at once there is a very small window for trouble in which both clients could attempt to insert with the same serial number. This is very unlikely but still possible. So I'm wondering if there is (a) A way to move the serial number calculation code to the server and take the serial number out of the insert statement. (b) Having a taken the serial number out of the insert statement, for the VB client to have an iron clad way retrieving the serial number that it just created (most recently created record wouldn't be sufficient since it would run into the same vulnerability of multiple clients trying to do the same thing at once).

    L P M B 4 Replies Last reply
    0
    • A Aaron Hartley

      I have a VB program that uses SQL Server as a database. One of the tables has a primary key, a serial number, that is inserted as part of the insert statement. The VB program determines the correct serial just prior to creating and executing the insert statement. The serial number not an incrementing value but is an aggregate of several pieces of information. Since I have copies of the same VB program running at once there is a very small window for trouble in which both clients could attempt to insert with the same serial number. This is very unlikely but still possible. So I'm wondering if there is (a) A way to move the serial number calculation code to the server and take the serial number out of the insert statement. (b) Having a taken the serial number out of the insert statement, for the VB client to have an iron clad way retrieving the serial number that it just created (most recently created record wouldn't be sufficient since it would run into the same vulnerability of multiple clients trying to do the same thing at once).

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      Use an IDENTITY[^] column and read the latest identity using the SCOPE_IDENTITY[^] function.

      A 1 Reply Last reply
      0
      • L Lost User

        Use an IDENTITY[^] column and read the latest identity using the SCOPE_IDENTITY[^] function.

        A Offline
        A Offline
        Aaron Hartley
        wrote on last edited by
        #3

        Thank you responding. I will read through the documentation completely. But just at a first glance wouldn't this run into the issue of 2 clients inserting at the same time but then they both fetch the same serial number. To put it another way, client A should get 12345, client B should get 12346, but due to the timing of the inserts they both get 12346.

        L L 2 Replies Last reply
        0
        • A Aaron Hartley

          Thank you responding. I will read through the documentation completely. But just at a first glance wouldn't this run into the issue of 2 clients inserting at the same time but then they both fetch the same serial number. To put it another way, client A should get 12345, client B should get 12346, but due to the timing of the inserts they both get 12346.

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          a new connection implies a new scope, SCOPE_IDENTITY will not return identities created through other connections. :)

          Luc Pattyn [My Articles] Nil Volentibus Arduum

          1 Reply Last reply
          0
          • A Aaron Hartley

            Thank you responding. I will read through the documentation completely. But just at a first glance wouldn't this run into the issue of 2 clients inserting at the same time but then they both fetch the same serial number. To put it another way, client A should get 12345, client B should get 12346, but due to the timing of the inserts they both get 12346.

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            As Luc has already answered on my behalf, SCOPE_IDENTITY() is scoped to your connection and ensures that you do not get a value that was inserted through another connection even if it were newer. There are other ways to read identity values though, but I suggested this method specifically for this reason.

            1 Reply Last reply
            0
            • A Aaron Hartley

              I have a VB program that uses SQL Server as a database. One of the tables has a primary key, a serial number, that is inserted as part of the insert statement. The VB program determines the correct serial just prior to creating and executing the insert statement. The serial number not an incrementing value but is an aggregate of several pieces of information. Since I have copies of the same VB program running at once there is a very small window for trouble in which both clients could attempt to insert with the same serial number. This is very unlikely but still possible. So I'm wondering if there is (a) A way to move the serial number calculation code to the server and take the serial number out of the insert statement. (b) Having a taken the serial number out of the insert statement, for the VB client to have an iron clad way retrieving the serial number that it just created (most recently created record wouldn't be sufficient since it would run into the same vulnerability of multiple clients trying to do the same thing at once).

              P Online
              P Online
              PIEBALDconsult
              wrote on last edited by
              #6

              I strongly agree with getting that off the client. How to do so may depend on exactly what information is used to generate the serial number. I've seen some that use the date and a sequence, e.g. 120313123 (YYMMDDseq), with the sequence rolling over each day. Something like that could be done in the database, by a stored procedure. I understand that the upcoming version of SQL Server will have sequences built in (Oracle has had them for decades), but you could also create your own sequence (which is what I do when I need a sequence). On the other hand, you probably shouldn't put any "information" in the serial number in the first place. As to using identity columns... I don't; I find them to be very problematic, and a simple sequence works much better in most cases.

              L 1 Reply Last reply
              0
              • P PIEBALDconsult

                I strongly agree with getting that off the client. How to do so may depend on exactly what information is used to generate the serial number. I've seen some that use the date and a sequence, e.g. 120313123 (YYMMDDseq), with the sequence rolling over each day. Something like that could be done in the database, by a stored procedure. I understand that the upcoming version of SQL Server will have sequences built in (Oracle has had them for decades), but you could also create your own sequence (which is what I do when I need a sequence). On the other hand, you probably shouldn't put any "information" in the serial number in the first place. As to using identity columns... I don't; I find them to be very problematic, and a simple sequence works much better in most cases.

                L Offline
                L Offline
                Lost User
                wrote on last edited by
                #7

                PIEBALDconsult wrote:

                As to using identity columns... I don't; I find them to be very problematic

                I've been using them for over a decade and haven't really found any problems.

                P J 2 Replies Last reply
                0
                • A Aaron Hartley

                  I have a VB program that uses SQL Server as a database. One of the tables has a primary key, a serial number, that is inserted as part of the insert statement. The VB program determines the correct serial just prior to creating and executing the insert statement. The serial number not an incrementing value but is an aggregate of several pieces of information. Since I have copies of the same VB program running at once there is a very small window for trouble in which both clients could attempt to insert with the same serial number. This is very unlikely but still possible. So I'm wondering if there is (a) A way to move the serial number calculation code to the server and take the serial number out of the insert statement. (b) Having a taken the serial number out of the insert statement, for the VB client to have an iron clad way retrieving the serial number that it just created (most recently created record wouldn't be sufficient since it would run into the same vulnerability of multiple clients trying to do the same thing at once).

                  M Offline
                  M Offline
                  Mycroft Holmes
                  wrote on last edited by
                  #8

                  As others have implied you need to change your strategy. Personally I would leave the serial number method exactly as it is but would not have it as the primary key. A primary key should hold no intelligence in it's data, so create another field (based on IDENTITY or GUID spit)) and use the serial no as a piece of clients code.

                  Never underestimate the power of human stupidity RAH

                  1 Reply Last reply
                  0
                  • A Aaron Hartley

                    I have a VB program that uses SQL Server as a database. One of the tables has a primary key, a serial number, that is inserted as part of the insert statement. The VB program determines the correct serial just prior to creating and executing the insert statement. The serial number not an incrementing value but is an aggregate of several pieces of information. Since I have copies of the same VB program running at once there is a very small window for trouble in which both clients could attempt to insert with the same serial number. This is very unlikely but still possible. So I'm wondering if there is (a) A way to move the serial number calculation code to the server and take the serial number out of the insert statement. (b) Having a taken the serial number out of the insert statement, for the VB client to have an iron clad way retrieving the serial number that it just created (most recently created record wouldn't be sufficient since it would run into the same vulnerability of multiple clients trying to do the same thing at once).

                    B Offline
                    B Offline
                    Bernhard Hiller
                    wrote on last edited by
                    #9

                    First of all, separate the serial number and the primary key. If you use a Guid as the key, you can "calculate" it (Guid.NewGuid()) already on the client. In case of an autoincrement value, you can query it from the database with a SELECT @@ID. Your serial number column should still have a unique index. When you insert your data, omit the serial number first. You can take two different approaches here: (1) Create a trigger. In the trigger function, calculate your serial number. Take care that two calculations may happen at the same time in different threads. The trigger function then updates your data. Retrieve the inserted serial number with a select query. (2) Calculate the serial number on the client. Do an update query. When the update fails due to a duplicate value, calculate again with adjusted parameters, and try again, till the update does not fail. Here, I'd use a transaction, and commit when the update was succesful. Looks bad, but with a low chance of duplicates, it will not cause bad performance.

                    1 Reply Last reply
                    0
                    • L Lost User

                      PIEBALDconsult wrote:

                      As to using identity columns... I don't; I find them to be very problematic

                      I've been using them for over a decade and haven't really found any problems.

                      P Online
                      P Online
                      PIEBALDconsult
                      wrote on last edited by
                      #10

                      I have used them infrequently -- only in apps that someone else wrote -- and have always had trouble. Using a sequence or GUIDs has never caused me trouble.

                      1 Reply Last reply
                      0
                      • L Lost User

                        PIEBALDconsult wrote:

                        As to using identity columns... I don't; I find them to be very problematic

                        I've been using them for over a decade and haven't really found any problems.

                        J Offline
                        J Offline
                        jschell
                        wrote on last edited by
                        #11

                        Shameel wrote:

                        I've been using them for over a decade and haven't really found any problems.

                        Neither have I. If I remember I will check my SQL 6.5 reference to see what I was using with that (since I have been using SQL Server longer than a decade.) * UPDATE * Yep 6.5 had them so I haven't had any trouble using them for 15 years.

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups