I'm using ##Identity to get identity of a particular row after successful insert on a table, but sometimes I'm getting someother identity other than what it created for a particular row.
Sample:
ID UserName Age Location
1 Andy 22 USA
2 Robert 24 Canada
3 James 26 Mexico
From above sample while getting identity for user 'Robert' some other created 'James' and I'm getting the lastest identity as '3' instead of '2'.
All this is happening in a ASP.NET website user registration, it's giving the latest identity for each connection object and the same connection object is using for all registrations.
Please some one help me this out how to get the exact identiy when some other people using same connection object to get the identity?
If i use SCOPE_IDENTITY() for the below query, I'm getting DBNULL exception while convertion.
cmd.Connection = conn;
conn.Open();
int intStatus = cmd.ExecuteNonQuery();
if (intStatus == 1)
{
SqlCommand cmd1 = new SqlCommand("Select SCOPE_IDENTITY()", conn);
id_package = Convert.ToInt32(cmd1.ExecuteScalar());
}
use SCOPE_IDENTITY() it will return the last identity value generated in your session.
##IDENTITY will return the last generated identity value in ANY session.
Also if you are inserting multiple rows you can use the OUTPUT clause too to get all the newly generated identity values in your session.
Use OUTPUT Clause
INSERT INTO YourTable (UserName, Age, Location)
OUTPUT inserted.ID
VALUES ("Andy", 22, "USA")
If ID is identity column, statement will return inserted ID by this query
I think you are looking for SCOPE_IDENTITY(). This will give you the identity value generated from your query or session
I don't know anything about asp.net, but it at least looks to me like you're creating a new database session to get the identity and that's why you get nulls. You'll have to fetch it in the same session where you have created the row (or use output clause).
Related
we are having issues with a stored procedure. When calling it from our website via asp/vb.net it seems to not be executing properly. If I run it from SSMS it works.
I have run the debugger when the call is being placed, the parameters being passed in are correct at the time of the ExecuteNonQuery() call but it is not generating any records in the related tables like it should. If I use the same values seen while debugging our website directly in SSMS, the stored procedure creates the expected records.
Here is our stored procedure:
ALTER PROCEDURE [dbo].[CopyGoals](
#OldVisitID int,
#NewVisitID int,
#CreatedBy NVarChar(30)
) AS BEGIN
declare #GoalMapping As Table(OldGoalID int,NewGoalID int);
Merge Into VisitGoals
Using(
select GoalsID,Goal,ProgressNote,Progress,Completed,CreatedOn,CreatedBy,VisitID
From VisitGoals
Where VisitID = #OldVisitID
) As Src
On 1 = 0
When Not Matched By Target Then
Insert (Goal,ProgressNote,Completed,VisitID,Progress, CreatedOn, CreatedBy)
Values (Src.Goal, Src.ProgressNote, Src.Completed, #NewVisitID, Src.Progress, GetDate(), #CreatedBy)
Output Src.GoalsID As OldGoalID, inserted.GoalsID as NewGoalID
Into #GoalMapping;
Insert Into SubGoals(GoalID,VisitID,GoalText,HasCompleted,WillComplete,GoalStatus)
(
Select GM.NewGoalID, #NewVisitID, SG.GoalText, SG.HasCompleted, SG.WillComplete, SG.GoalStatus
From SubGoals As SG inner join #GoalMapping As GM on SG.GoalID = GM.OldGoalID
Where SG.VisitID = #OldVisitID
)
END
Here is the procedure call from our website page:
Dim conStr As String = ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString
Dim curUsr As New Supervisor(Context.User.Identity.Name, True)
Using con As New SqlConnection(conStr)
Using cmd As New SqlCommand("CopyGoals", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#OldVisitID", SqlDbType.Int).Value = oldVID
cmd.Parameters.Add("#NewVisitID", SqlDbType.Int).Value = newVID
cmd.Parameters.Add("#CreatedBy", SqlDbType.NVarChar, 30).Value = curUsr.Name
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Using
End Using
What this procedure should do, and does if run from SSMS, is look at our Goals table with the existing IDs matching a foreign key corresponding to the VisitID in a different table to find all goals associated with that old visit.
It them copies the goal information and inserts it into the Goals table, outputting the old goal IDs and the newly inserted goal IDs into the #GoalMapping table.
It then looks into our SubGoals table and does a similar thing by copying each subgoal related to the goals we just copied. For whatever reason, this procedure does not execute properly when called from our page even when it runs in SSMS when we feed it the same input values as seen during debugging of the page. There are no errors reported in chrome's debugger, we tried wrapping execute in a try with an SQL and normal exception but neither of them tripped. We are pretty stumped. Maybe someone will spot something we haven't over the last few days.
Here is the output from Sql Profiler:
Okay, I finally figured it out. There was a permission issue as Mohsin suggested. I logged in as the user that we use for our ASP.net connection strings and attempted to run the query in question and it failed to generate the records from SSMS. So after some digging I found this question:
Stored Procedure and Permissions - Is EXECUTE enough?
Which lead to this question when I got the same error:
SQL Server principal "dbo" does not exist,
Combined together, the answers to these questions helped me fix the issue.
I am trying to write a paramaterized update query to insert values into an Sql Server Express Database. The query I have written is:
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandText = "update tblposts set title=#ptitle, pdate=#pd,
content=#pcontent where pid=#p"
cmd.Parameters.AddWithValue("ptitle", txtTitle.Text)
cmd.Parameters.AddWithValue("pcontent", txtcontent.InnerText)
cmd.Parameters.AddWithValue("pd", DateTime.Now.ToString)
cmd.Parameters.AddWithValue("p", postid)
On running cmd.ExecuteNonQuery, I get number of rows affected as 1, but the change is not reflected in the database.
On printing the query using Debug.Write, I get the query not with the parameter values, but the names of the parameters itself (ie. #pcontent, #title etc)
What can be the mistake here?
In you're AddWithValue you need to include the # symbol on the front of the parameter, so:
cmd.Parameters.AddWithValue("#ptitle", txtTitle.Text)
cmd.Parameters.AddWithValue("#pcontent", txtcontent.InnerText)
cmd.Parameters.AddWithValue("#pd", DateTime.Now.ToString)
cmd.Parameters.AddWithValue("#p", postid)
I'm guessing that it's executing correctly but there where clause is blank, so perhaps updating a blank row.
Anyway, try the above and it should update as expected.
Edit to Add
The CommandText will always only have the #value in there, it will not substitue the parameter values into the string.
You would need to loop through the cmd.Parameters collection to write out the values.
I have a web form that inserts a row into an SQL Server 2008 table. Table has a field which must be unique, but for some reasons we are not allowed to use autoincrement utility. Instead of this I select the maximum of this field and increment it from code and insert the row with that id.
The problem is, if more than one person uses this form simultaneously, there occurs a concurrency problem and same id will be inserted to the table. I do not know how to solve this issue in a asp.net web project because all users have their own session and threads.
Any idea on how to manage concurrency problems in asp.net project will be very useful.
Thanks.
If you perform the insert into a stored procedure, or in a transaction in the code, I don't see a reason to have problems with concurrency. Something like:
BEGIN TRAN
DECLARE #MAX int
SELECT #MAX = MAX(ID) FROM MyTable
INSERT INTO MyTable (#MAX, VAlue, Value2..)
COMMIT TRAN
or
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
transaction = connection.BeginTransaction("InsertRow");
... perform insert using command object ...
transaction.Commit();
Sometimes when I insert a new row to a table in my database, it comes before the last row.
I will explain. If I have the following table:
ID Name
1 James
2 Terry
3. Miriam
4. Arthur
and I want to insert a new row with "Danny", sometimes this happens:
ID Name
1 James
2 Terry
3. Miriam
5. Danny
4. Arthur
My code works in 99 percent of the cases, but sometimes it just happens.
I do not know what to do? Is this normal?
I work with ASP.NET, VB.NET, .NET 3.5 and MySQL database with autoIncrement on the ID column.
I've seen it also happen in Access and SQL Server.
This is my code:
' insert to user_table
Dim connString As String = ConfigurationManager.ConnectionStrings("mysql_ConnString").ConnectionString
Dim conn As MySqlConnection = New MySqlConnection(connString)
Dim sqlCommand As String
sqlCommand = "INSERT INTO user_table (Nickname,Email,Pass,SubscriptionMode,SignupDate,LastVisitDate,VisitCounter) VALUES (#Nickname,#Email,#Pass,#SubscriptionMode,#SignupDate,#LastVisitDate,#VisitCounter)"
Dim cmd As New MySqlCommand(sqlCommand, conn)
Try
conn.Open()
cmd.Parameters.AddWithValue("#Nickname", txtNickname.Text)
cmd.Parameters.AddWithValue("#Email", txtEmail.Text)
cmd.Parameters.AddWithValue("#Pass", password)
cmd.Parameters.AddWithValue("#SubscriptionMode", 1)
cmd.Parameters.AddWithValue("#SignupDate", Date.Now)
cmd.Parameters.AddWithValue("#LastVisitDate", Date.Now)
cmd.Parameters.AddWithValue("#VisitCounter", 0)
cmd.ExecuteNonQuery()
Catch ex As Exception
GlobalFunction.sendToLog(ex, "problem in create profile page - sub: insertUser_table")
GlobalFunction.jsMessage(Me, "problem in create profile page - sub: insertUser_table")
Return False
Finally
conn.Close()
End Try
In general, when you do
select * from Users
you cannot rely on the order of records. if you need your records in some particular order, you'll have to explicitly specify an order by clause
select * from Users order by ID
MySql is a Relational Database Management System which means that it is based on the relational model. The physical order of the rows of a table (which represents a relation) is of no importance. You must think of tables as Unorder Sets. If you want to present your data in a specific order you must use the order by clause.
I think that if you use InnoDB you can use a clustered index to specify the order of the rows.
To correct your question: My database table is not ordered
Your database table is ordered, but your select statement is not ordered.
And because it is not that's why you're not getting an ordered result.
The result that you are getting is in undefined order!
If you want an ordered result you must always specify and order by clause in your query.
Make ID your primary key and make it indexed. No matter what your newly entered row will be the last one. For selecting use the suggestions above about order by.
As Bala R said, you can't have SQL determine how you want to organize your data, so you want to do something like this:
SELECT * FROM Users ORDER BY id ASC
ex: (1,2,3,4,5)
Or this:
SELECT * FROM Users ORDER BY id DESC
ex: (5,4,3,2,1)
I have a SQL database that creates a record for every document uploaded by the user to the server. I want to check this table before a user uploads a document to ensure they don't upload a file with name that already exists.
I know how to make the connection and make the SqlCommand to query the table for an existing record. But I don't know how to check the record count from the sqlCommand I made.
Does that make sense?
Using myConnectionCheck As New SqlConnection(myConnectionStringCheck)
Dim myCommandCheck As New SqlCommand()
myCommandCheck.Connection = myConnectionCheck
myCommandCheck.CommandText = "SELECT * FROM Req_Docs WHERE Doc_Name =" & DocName
myConnectionCheck.Open()
myCommandCheck.ExecuteNonQuery()
End Using
Thanks in advance,
Anthony
use if exists for this issue
create procedure isDocExists
#DocName varchar(255),
#isExists bit output
as
set #isExists = 0
if exists (SELECT Doc_Name FROM Req_Docs WHERE Doc_Name =#DocName)
begin
set #isExists=1
end
to check where record is there or not
So many things wrong here:
Race condition between when you check and when you upload
Multiple Documents should legitimately be allowed to have the same name. Use tags, folders, timestamps, or other means to distinguish them.
Sql Injection vulnerability on the name parameter
ExecuteNonQuery() on a SELECT query.
I'll give you the benefit of the doubt on the first two points that you're still gonna allow the upload, and this is just so you can ask the user how they want to relate the documents. Given that, here's how you fix the other two:
Using cn As New SqlConnection(myConnectionStringCheck), _
cmd As New SqlCommand("SELECT COUNT(*) FROM (SELECT TOP 1 1 FROM Req_Docs WHERE Doc_Name= #DocName) t", cn)
cmd.Parameters.Add("#DocName", SqlDbTypes.VarChar, 255).Value = DocName
cn.Open()
Return CInt(cmd.ExecuteScalar())
End Using
ExecuteNonQuery is a function, that returns an integer equal to the number of rows affected by the query.
However, it's usually used for updates.
You might consider ExecuteScalar, which returns the first column of the first row in the result set.
So if you change the query to select count(*) from..., the result of ExecuteScalar will be the number of rows, which you can then test.
if you want count:
SELECT COUNT(*) as count FROM Req_Docs WHERE Doc_Name = 'DocName'