Showing posts with label record. Show all posts
Showing posts with label record. Show all posts

Wednesday, March 28, 2012

Persistent autoincrementing value, not attached to row insertion?

I need to get a unique value to use for a record *before* the record is added to a table. It doesn't have to be contiguous with existing records, but it must always be unique, has to be persistent over multiple instantiations of an ASP.NET application, and has to work in that sort of a multi-session environment (where other sessions could need additional unique values before the first session gets around to actually adding a record to the table).

I considered generating and using unique CLSIDs for this, but the resulting value also needs to become part of the filename of some files that are being saved to the disk (and those names also saved in the table), and including text CLSIDs along with other filename data would make for some unpleasantly long and difficult to work with filenames.

I also don't think there's a practical way for me to use a trigger associated with an identity column for this, because I need to save files to disk using the unique value before I even know if the record will in fact end up being added to the table, and what's more, the numbers and names of those files will vary in ways that might be difficult to handle in a stored procedure.

What I'm thinking I will have to do is create a separate database table called something like "UniqueIDGen". This table would have a single record in it with a single integer value, initialized to a value of 1. Then, each time an ID is needed, this one record would be locked, read and incremented by 1. The only reason for doing it this way instead of with an application variable, as I see it, is that the values need to be unique and continue incrementing in perpetuity, no matter how many times the ASP.NET application is recycled or the server is rebooted.

But I still have to wonder if there might be a more efficient method provided by SQL Server for this type of unique value generation ... something that is equally as persistent without requiring an entire table with only a single record to be allocated to such a basic task. Does anyone know of a more elegant solution for this?do a hash of the current date.time.milliseconds, or a unix timestamp in the backend of the asp.net, unless you plan on data being entered in the same second.|||Is there no better option based upon SQL Server or some other persistent technology, other than the workable but awkward solution I mentioned? For some reason I thought there might be a non-table-based identity value, or something like that, specifically for situations like this. Perhaps that is something I'm remembering from some other RDBMS software I dealt with in the past, and not SQL Server?|||Hi,

You could do this, it is a bit like Oracle's NextVal:

CREATE TABLE dbo.Sequences
(
ID int NOT NULL
)

INSERT INTO Sequences (ID) VALUES (0)

CREATE PROCEDURE dbo.NextValue
@.ID int output
AS
UPDATE Sequences SET ID = ID + 1, @.ID = ID + 1
RETURN

And call the stored proc to get the ID.


private void Button1_Click(object sender, System.EventArgs e)
{
string connectionString = @."Server=wpeude-masonix2;Database=TestDatabase;User ID=sa;Password=sa;Trusted_Connection=False";

SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "dbo.NextValue";
command.CommandType = CommandType.StoredProcedure;

SqlParameter param = new SqlParameter("@.ID", SqlDbType.Int, 4);
param.Direction = ParameterDirection.Output;
command.Parameters.Add(param);

connection.Open();
command.ExecuteNonQuery();
int pk = (int)param.Value;
connection.Close();
lblNextValue.Text = pk.ToString();
}

The ID would be unique in the Database. You could change the sproc to use NEWID() and have a varchar column instead, if you wanted to use a GUID.

A.|||asmason,

Your example is precisely the solution I proposed in my original post (unless I did an insufficient job of describing what I was thinking of). If there's no method available that's superior to creating a table for this purpose, then I'll go ahead and do it that way.

Thanks for taking the time to write it up.|||Couldn't you take and make a stored procedure that makes it for you? Basically when you go to insert a value you do a :


select @.IDVariable = Max(IDField) from Table

Then when you insert:

 Insert into Table (IDField) Values (@.IDVariable)

I have done something very similar to this in several projects and it remains unique and it is available when you create it.|||Regarding the suggestion of:

select @.IDVariable = Max(IDField) from Table

... and then ...
Insert into Table (IDField) Values (@.IDVariable)

I don't think I should do that. In my case, fair amount of time (seconds or even minutes) can potentially elapse between the time I need the unique ID (the first line) and the actual INSERT (the second line). What happens when, when session #1 is sitting at some point in between those two statements, and session #2 comes along and performs the first statement to get an ID for itself? It will get the same one that the first session got ... and then. if both sessions end up inserting a new row using the provided ID ... *biff*, collisions.

In fact, generally it seems like this wouldn't be wholly safe in any multi-threaded environment (even a delay of milliseconds could theoretically lead to a collision, though it might be much less likely than in my current project). Maybe it would be okay if both statements were encased within a single transaction, but that doesn't allow the ID value to be used for things outside of the database, which is a requirement of what I'm working on.

Also, I can only assume that the performance of the MAX function degrades as the number of rows in the table increases, so that may be a bit of a negative as well, at least compared to the standalone "ID table" method.

For what it is worth, I've already gone ahead and implemented a table for this task, very similar to the code that asmason included above, and it works very nicely. I did add one thing: a "counter_name" field, so that the same table could be used to maintain additional unique counters or values if I run across similiar needs again in the future. Thus, the statement in my stored procedure looks like this:

UPDATE AppCounters SET id = id + 1, @.RETURNID = id + 1 WHERE counter_name = @.ctrname

Per-record processing?

Hi,

I am looking for a way to process each record from a SELECT query. Each record has to go through a stored procedure to be validated and different actions have to be taken depending on whether or not it passes the validation.

I'm a bit new to Transact SQL. My background is in programming, so I keep wanting to visualize a loop, which doesn't exist in TSQL, from what I understand. Can anyone help me understand how something of this type would be done?

Thank you!

SQL Server is designed for SET based operation. 'Per-Record' operations are often best left to a client application.

However, in some situations, it may be necessary to (a) gather relavent records into a temporary table, (b) set a counter variable with the @.@.Rowcount from the temporary table, (c) use a WHILE @.CurrentRecord < @.RecordCount type of loop.

However, this is guarenteed to be a non-optimal use of SQL Server. Perhaps if you were to post the select query, the stored procedure, and some sample data, folks here would help you properly design a SET based operation -if possible.

|||Thank you. I think this is just what I needed to move this into a .Net app.sql

Monday, February 20, 2012

Permission error when trying to INSERT data

I have a user trying to insert a record into a table on my SQL 2000 server.
When she tries to do the insert she gets a message "Insert permissions denie
d
on object 'mytable', database 'mydatabase', owner 'dbo'". This user is a
member of an Active Directory group on my network. The AD group has rights t
o
the database on my SQL Server. The AD group has select, insert, update and
delete rights to the table in question. Yet even after all of this she is
still unable to insert records into this table.
What could be causing my problem? We recently changed the service log on
user for the MSSQLServer logon. I wouldn't expect this to make any differenc
e
in her ability to insert a record into this table. Am I wrong?
Any help would be greatly appreciated.Hi,
By any chance some one DENY INSERT to this user for this table.
Thanks
Hari
SQL Server MVP
"Snowmizer" <Snowmizer@.discussions.microsoft.com> wrote in message
news:104EB25F-C2F7-46A3-8A5B-7B9AC61A6F16@.microsoft.com...
>I have a user trying to insert a record into a table on my SQL 2000 server.
> When she tries to do the insert she gets a message "Insert permissions
> denied
> on object 'mytable', database 'mydatabase', owner 'dbo'". This user is a
> member of an Active Directory group on my network. The AD group has rights
> to
> the database on my SQL Server. The AD group has select, insert, update and
> delete rights to the table in question. Yet even after all of this she is
> still unable to insert records into this table.
> What could be causing my problem? We recently changed the service log on
> user for the MSSQLServer logon. I wouldn't expect this to make any
> difference
> in her ability to insert a record into this table. Am I wrong?
> Any help would be greatly appreciated.
>