VB6 application - automatically incremented number check - sql-server

I'm building a small application and I came across an issue that I need to resolve. When I insert a new client into the SQL-SERVER I need to create an ID number to go with the client. I have a value, say - 1000 in a reference table, that gets pulled from the table, incremented by 1, then put back into the ref table, and the value 1001 gets assigned to the client. Before it gets saved to the client, I add 'TOL' to the number - so when save is complete, the ID is TOL1001. The issue I need to resolve is to check the tblClient_TABLE, to make sure that ID TOL1001 doesn't exist already before doing the insert for a new client.
I'm not really sure where I should do it, because on SAVE, I call the function that increments the number, assigns TOL to it and stores the value in an invisible textbox, so when I do my insert, it just pulls the value from the textbox...
strSQL = "INSERT into tblClient_TABLE (ID) values ("txtIDnumber.text")
I obviously have more data to insert, it's just i'm struggling with finding a logic way to check for the already existing ID.
Thanks for any ideas, help!

Your database is able to use identity columns (=autoincrement). So, if you insert a new record, an identity column will get the next value (you can rely on the uniqueness).
How do you get this number? The insert statement has (for mssql) an "output inserted" clause, and if you use ado with executescalar you get your inserted id.
The SQL command (add the vb6 code for ado command you must)
INSERT INTO [TABLENAME] ( [COL1], [COL2] ) OUTPUT INSERTED.MYID VALUES ( #COL1, #COL2 )
... add your Parameter values here ....
result = adoCommand.ExecuteScalar()
(something like that, don´t have VB6 at the office ...)

Related

Temp table dropping immediately after query finishes

If I highlight then execute lines 1-4, I get output
Commands completed successfully.
Then, if I highlight and execute lines 6-14, I get output message
Invalid object name '#TestThis'
If I highlight and execute lines 1 - 16, I can see the one row of data returned. Why would a temp table that was just created (in the same session) immediately be dropped/invalid right after the code was executed? We're running this on an Azure based SQL Server.
If the session remains alive, the temporary table should still exist and be accessible. Make sure you are executing the create statement and the other ones on the same session and you are not getting a disconnection message in between.
Make sure you have the "Disconnect after the query executes" check in SSMS OFF.
If it still fails, do this check:
Create your temporary table, and keep the session alive (don't close the tab or disconnect it):
CREATE TABLE #TestThis (oldvalue INT, newvalue INT)
On a different session, query tempdb like the following:
SELECT * FROM tempdb.sys.tables WHERE [name] LIKE N'#TestThis%'
You should be able to see the temporary table created on the other session, starting with the same name and getting a bunch of underscores and some numbers at the end. This means the table still exists and you should be able to access it from the original session.
If you open a 3rd session and create the same temporary table, 2 of these should be listed on the tempdb query:
Matthew Walk You can try this solution as I showed in the example below.
CREATE TABLE #TestThis(oldvalue INT, newvalue INT )
INSERT INTO #TestThis(oldvalue, newvalue) VALUES (1,3),(5,7)
select oldvalue, newvalue FROM #TestThis
IF OBJECT_ID('tempdb..#TestThis') IS NOT NULL DROP TABLE #TestThis
In this example you need to check object id is null or not for your temptable, if it is not null then you need to drop your temp table.
I hope this helps you.
A session is created every time you click the execute icon, so yes, if you don’t highlight the “create table” part, the table wouldn’t exist.
You can either remove the hash (#) in front of the table name if you want the table to stay in the db until you drop it .... or also highlight the create table part every time you click “execute” ....whichever fits your needs better.
"#Temp" table is session level. If the database connection or session closed, the object "#TestThis" will be deleted.
You must keep the session going.
You should first highlight execute lines 1-4 to create the temp table "#TestThis" if not exist.
CREATE TABLE #TestThis
(
oldvalue INTEGER,
newvalue INTEGER)
Then you can execute lines 6-14. If you don't first create the temp table, how can you insert the data to temp table "#TestThis"?
Now you can execute:
INSERT INTO #TestThis
(
oldvalue,
newvalue
)
VALUES
( 1234,
7788
)
Or
SELECT * FROM #TempThis
Hope this helps.
It turns out the cause of this issue was using MFA instead of Active Directory password. Once the connection was switched to Active Directory password, the temp tables were created and accessible and persisted as expected.

How does SQL Server handle failed query to linked server?

I have a stored procedure that relies on a query to a linked server.
This stored procedure is roughly structured as follows:
-- Create local table var to stop query from needing round trips to linked server
DECLARE #duplicates TABLE (eid NVARCHAR(6))
INSERT INTO #duplicates(eid)
SELECT eid FROM [linked_server].[linked_database].[dbo].[linked_table]
WHERE es = 'String'
-- Update on my server using data from linked server
UPDATE [my_server].[my_database].[dbo].[my_table]
-- Many things, including
[status] = CASE
WHEN
eid IN (
SELECT eid FROM #duplicates
)
THEN 'String'
ELSE es
END
FROM [my_server].[another_database].[dbo].[view]
-- This view obscures sensitive information and shows only the data that I have permission to see
-- Many other things
The query itself is much more complex, but the key idea is building this temporary table from a linked server (because it takes the query 5 minutes to run if I don't, versus 3 seconds if I do).
I've recently had an issue where I ended up with updates to my table that failed to get checked against the linked server for duplicate information.
The logical chain of events is this:
Get all of the data from the original view
The original view contains maybe 3000 records, of which maybe 30 are
duplicates of the entity in question, but with 1 field having a
different value.
I then have to grab data from a different server to know which of
the duplicates is the correct one.
When the stored procedure runs, it updates each record.
ERROR STEP - when the stored procedure hits a duplicate record, it
updates my_table again - so es gets changed multiple times in a row.
The temp table was added after the fact when we realized incorrect es values were being introduced to my_table.
'my_database` does not contain the data needed to determine which is the correct tuple, hence the requirement for the linked server.
As far as I can tell, we had a temporary network interruption or a connection timeout that stopped my_server from getting the response back from linked_server, and it just passed an empty table to the rest of the procedure.
So, my question is - how can I guard against this happening?
I can't just check if the table is empty, because it could legitimately be empty. I need to definitively know if that initial SELECT from linked_server failed, if it timed out, or if it intentionally returned nothing.
without knowing the definition of the table you're querying you could get into an issue where your data is to long and you get a truncation error on your table.
Better make sure and substring it...
DECLARE #duplicates TABLE (eid NVARCHAR(6))
INSERT INTO #duplicates(eid)
SELECT SUBSTRING(eid,1,6) FROM [linked_server].[linked_database].[dbo].[linked_table]
WHERE es = 'String'
-- Update on my server using data from linked server
UPDATE [my_server].[my_database].[dbo].[my_table]
-- Many things, including
[status] = CASE
WHEN
eid IN (
SELECT eid FROM #duplicates
)
THEN 'String'
ELSE es
END
FROM [my_server].[another_database].[dbo].[view]
I had a similar problem where I needed to move data between servers, could not use a network connection so I ended up doing BCP out and BCP in. This is fast, clean and takes away the complexity of user authentication, drivers, trust domains. also it's repeatable and can be used for incremental loading.

T-SQL - SELECT SCOPE_IDENTITY does not work in vba code

I am working on a project which consists transferring a few thousands of Excel rows to a SQL Server (it was also called T-SQL if I'm right?) database. I put together some logic in VBA to shape up the data.
Let me give you some context first about this. The data I'm about to transfer are invoice files. On each row, there are code of the stock items, prices, invoice number, invoice date, name of the client etc. These needs to be transferred to the database of a proprietary ERP system.
There are two tables on the database which I'm interested in for now. First one holds the header data for the invoice (client data, date, invoice number, invoice total etc.). Second table holds the information on the stock items (what has been sold, how many and for how much money etc).
After each insert onto the first table, I have to get the inserted row's primary key, in order to insert rows to the second table, which requires the PK of the first table on each row.
Now, my approach was to use the SCOPE_IDENTITY() function of the T-SQL. When I try to do it on the database directly via SQL Server Management Studio, it works without a hitch.
But when I try to use it in the code, it returns an empty recordset.
Code I'm using is as follows:
Public Function Execute(query As String, Optional is_batch As Boolean = False) As ADODB.Recordset
If conn.State = 0 Then
OpenConnection
End If
Set rs = conn.Execute(query) 'this is the actual query to be executed
Dim identity As ADODB.Recordset 'this rs supposed to hold the PK of inserted row, but returns an empty recordset
Set identity = conn.Execute("SELECT SCOPE_IDENTITY();")
If TypeName(identity.Fields(0).Value) = "Null" Then
pInsertedId = -1
Else
pInsertedId = identity.Fields(0).Value 'I'm saving it in an object variable, to access it easily later on
End If
Set Execute = rs 'to be returned to the caller
'closing the connection is handled outside this procedure
End Function
When I run this on VBA, second query SELECT SCOPE_IDENTITY();just returns an empty recordset. Same query works successfully when ran on the db directly.
Actually I'm able to pull this off by other means. There is a UUID column which I'm supposed to insert to the row in the first table. I can just simply query the table with this UUID and get the PK, but I'm just curious why this won't work.
Any ideas?
Your code doesn't insert any data, so no identity values are generated in the current scope, as defined in the official documentation for SCOPE_IDENTITY():
Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, if two statements are in the same stored procedure, function, or batch, they are in the same scope.
Your code effectively is the same as inserting data in one query window in SSMS and querying SCOPE_IDENTITY() in another query window. Well, this isn't how it works. You must query it in the same scope, i.e. a stored procedure, trigger, function, or batch. Otherwise, use ID values generated by you and insert them with the data.

safe tsql Numbering int techniques

Hello stackOverflowers !
i was wondering if theres a way to get in a safe way, series of numbers in transactions just like the identity.My only purpose is for grouping rows in tables and i don't mean row_number().
i've came up with this simple query, is this safe?
this table has its own identity key
declare #mynextSecuenceNumber int
select #mynextSecuenceNumber=isnull(max(secuencenumber+1),1) from mytable
insert into mytable (productID,customer,secuencenumber) values (#someval,#anotherval,#mynextSecuenceNumber)
EDIT
THE BACKGROUND
the reason for doing this is the next:
first i'm recieving autoparts for car services then i generate a ticket for that recepcion(i can recieve one,two,three auto parts) later on i can continue on reciving autoparts for that specific car service from the same autopart provider or from a different provider but i want to be able to re generate the event or the ticket otherwise i'll end up querying the service and all the the autoparts associated with that or the provider and i wont know the event what i recived in that operation and on top of that i need another specific id for all those autoparts associated with that car service.
by the way i'm on sql server 2008
heads up
using identity as secuence number can be messy cus transactions will increment the value after rolling back and other issues so be aware of that thanks to the approach privided as my acepted answer i can find another way who gets along with transactions its the first to appear on the link
Here's a scalable recommendation from Microsoft when SQL 2012 or higher isn't an option, but you need to manage sequence numbers without identities in the target table. This creates a separate table to track the sequence numbers, let's identity do some of the heavy lifting, and keeps the table size minimal by cleaning up. If this load becomes too much, you can schedule something for the cleanup during off-peak time.
-- Create table for tracking the sequence
create table <tablename> (
SeqID int identity(1,1) primary key
)
GO
-- Create procedure to return next sequence value
create procedure GetNewSeqVal_<tablename>
#NextValue int output
as
begin
declare #NewSeqValue int
set nocount on
insert into <tablename> DEFAULT VALUES
set #NewSeqValue = scope_identity()
delete from <tablename> with (readpast)
set #NextValue = #NewSeqValue
end
go
-- Get next sequence
declare #seqId int
exec GetNewSeqVal_<tablename> #NextValue = #seqId OUTPUT
For more info: http://blogs.msdn.com/b/sqlcat/archive/2006/04/10/sql-server-sequence-number.aspx

DataAdapter Update() requires input parameter for Auto increment primary key column

While updating a DataTable to a SQL Server database I get the error message "Column 'PK_Column' does not allow nulls" after calling GetErrors()
I don't want to provide a value for PK_Column because it is a auto increment primary key column in the database. My insert statement looks like this:
INSERT INTO [Order] ([Customer_Id], [OrderTime], [OrderType])
VALUES(#Customer_Id, #OrderTime, #OrderType)
SELECT CAST(SCOPE_IDENTITY() AS int) AS '#PK_Column'
It works as expected in SQL Server Management Studio, so the query is obviously not the problem.
I have four parameters on the insert command, one output parameter (#PK_Column) and three input parameters (#Customer_Id, #OrderTime, #OrderType). I figured out that I don't get the error if I set #PK_Column to InputOutput parameter, but then the PK_Column value does not get updated with the correct value created by the database.
Try
SELECT #PK_Column = SCOPE_IDENTITY()
This way, you assign to the local variable #PK_Column, which is picked up as a parameter.
When you do ... AS '#PK_Column', you are creating a data set with one column called "#PK_Column", when you want to assign a value to local var/parameter #PK_Column
Note: ... AS #PK_Column would fail because this is column alias. You're relying on a setting that allows '#PK_Column' to be a valid alias where as #PK_Column would fail

Resources