Getting the identity value from a table with single identity column in FitNesse - sql

Does FitNesse/dbFit support inserting into a table with a single identity column and then returning that value into a variable?
For example:
create table TestTable ( ID int identity(1,1) )
!|Insert|TestTable|
|ID? |
|>>TestID |
results in the following exception:
System.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near ')'.
Is there another way to accomplish this?

Your problem is not with Fitnesse, but with the SQL engine. If you try the same query in SQL Server Management Studio you will receive the same error. Thus, given the restriction that you cannot use set identity_insert on the question you really need to ask is how to insert a record with no insertable fields in SQL Server independent of Fitnesse? This StackOverflow post provides a simple answer:
INSERT INTO #TempTable DEFAULT VALUES
Having that in hand, now the task is to map this to Fitnesse. Here is one solution:
!|execute|CREATE TABLE #TestTable ( ID int identity(1,1) )|
!|execute|INSERT INTO #TestTable DEFAULT VALUES|
!|query|SELECT TOP 1 ##IDENTITY [ID] FROM #TestTable|
|ID? |
|>>TestID |
Fitnesse's INSERT command does not support the default construct, so you must switch to the more general EXECUTE command to do the insert. That, however, does not return results so you cannot glean the auto-inserted ID value directly. The final query gives you one way to grab the just-inserted identity value.

Related

Need to create a Run id for each package run in SSIS Package

I have an SSIS Package that runs a query and inserts values into a different table. Each time the package runs, I want to create a unique RunID for the results of that run. Here are the columns from my table. I have tried this using the Execute SQL Task and setting up the User::RunID variable but, I believe I am doing something wrong. Can anyone provide step by step instructions on how to do this?
You need 2 tables for this.
create table runs(
runID int identity primary key,
runDateTime datetime default getdate()
)
create table runReturns(
runReturnsID int identity primary key,
runID int not null,
[the rest of the data set]
)
In ssis, start with an execute SQL.
Add this query...
insert into runs (runDateTime) values(?);
select SCOPE_IDENTITY()
Map the parameter (?) to Now();
Change the result set to single row and map the first column to a parameter called runID.
Now create a data flow.
Insert your query into a sql source.
Add a derived column and map a new column to runID.
Finally, add a destination to your table and map accordingly.
Adding a completely sql answer to compliment as an alternative since there are no transformations at all:
Same 2 tables:
create table runs(
runID int identity primary key,
runDateTime datetime default getdate()
)
create table runReturns(
runReturnsID int identity primary key,
runID int not null,
[the rest of the data set]
)
Create a Job.
Add a step and base it on SQL.
declare #runID int;
insert into runs(runDateTime) values(getdate());
select #runID = scope_idenity();
insert into runReturns(
runID, [rest of your columns])
select #runID
, [rest of your columns]
from [rest of your query]
An approach that might solve the issue, is the system scoped variable ServerExecutionID By default, System scoped variables are hidden in the Variables menu but you can expose them by clicking the Grid options button (rightmost of the 5).
If you reference that variable using the appropriate placeholder (? for OLE/ODBC or a named parameter for ADO) and map to the variable, then every server execution will have a monotonically increasing number associated to it. Runs from Visual Studio or outside of the SSISDB, will always have a value of 0 associated to them but given that this is only encountered during development, this might address the issue.
Sample query based on the newer picture
INSERT INTO dbo.RunMapTable
SELECT ? AS RunID
, D.Name
FROM
(
VALUES ('A')
, ('B')
, ('C')
, ('D')
)D([name];
Parameter Mapping
0 -> System::ServerExecutionID
As an added bonus, you can then tie your custom logging back to the native logging in the SSISDB.

On SQL INSERT can I use the identity column for part of the insert data in another column at the same time?

CREATE TABLE Table1 :
Id int IDENTITY(1,1),
PK_Column1 nvarchar(50) Primary Key.
INSERT INTO Table1 (PK_Column1) VALUES ('Name'+Id)
Result:
Id PK_Column1
1 Name1
Is this possible? Or do I need to manage the Id column myself for this to work?
From the documentation:
After an INSERT, SELECT INTO, or bulk copy statement completes, ##IDENTITY contains the last identity value generated by the statement.
This applies to all the other identity checkers.
You should probably write a little SP to update the record immediately after your insert if this is what you need. Given that your primary_key appears to be some unusual composite of the ID and a varchar, you would also be best reviewing your data model.
It's important to note the difference with ##IDENTITY and SCOPE_IDENTITY():
##IDENTITY and SCOPE_IDENTITY return the last identity value generated in any table in the current session. However, SCOPE_IDENTITY returns the value only within the current scope; ##IDENTITY is not limited to a specific scope.

SQL insert into with Hsqldb Script

I am trying to initialise my hsqldb with some default data but seem to be having a problem with identity and timestamp columns.
I just realised that I probably wasn't clear what I meant when I said "script". I am meaning the command line argument that you pass to hsqldb to generate your database at startup. I can successfully run the query inside DbVisualiser or some other database management tool.
I have a table with the following definition:
create table TableBob (
ID int NOT NULL identity ,
FieldA varchar(10) NULL,
FieldB varchar(50) NOT NULL,
INITIAL_DT timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);
I can successfully create this table using the script but trying to insert a record doesn't work. Below is what I would consider valid sql for the insert since the ID and INITIAL_DT fields are Identity and Default columns). Strangely it inserts null into every column even though they are defined as NOT NULL....
e.g.
INSERT INTO TableBob (FieldA, FieldB) VALUES ('testFieldA', 'testFieldB');
Thanks for your help
Please try with HSQLDB's DatabaseManagerSwing (you can double click on the hsqldb.jar to start the database manager). First execute the CREATE TABLE statement, then the INSERT statement, finally the SELECT statement.
It should show the correct results.
If you want to use a script to insert data, use the SqlTool.jar which is available in the HSQLDB distribution zip package. See the guide: http://hsqldb.org/doc/2.0/util-guide/

Get the last inserted row ID (with SQL statement) [duplicate]

This question already has answers here:
How to get last inserted id?
(16 answers)
Closed 10 years ago.
I want to get the new created ID when you insert a new record in table.
I read this: http://msdn.microsoft.com/en-us/library/ms177564.aspx but it needs to create temporary table.
I want to return the ID after executing INSERT statement (assuming executing just one INSERT).
Example:
1 Joe Joe
2 Michael Mike
3 Zoe Zoe
When executing an INSERT statement, I want to return the created ID, means 4.
Can tell me how to do that using SQL statement or it is not possible ?
If your SQL Server table has a column of type INT IDENTITY (or BIGINT IDENTITY), then you can get the latest inserted value using:
INSERT INTO dbo.YourTable(columns....)
VALUES(..........)
SELECT SCOPE_IDENTITY()
This works as long as you haven't inserted another row - it just returns the last IDENTITY value handed out in this scope here.
There are at least two more options - ##IDENTITY and IDENT_CURRENT - read more about how they works and in what way they're different (and might give you unexpected results) in this excellent blog post by Pinal Dave here.
Assuming a simple table:
CREATE TABLE dbo.foo(ID INT IDENTITY(1,1), name SYSNAME);
We can capture IDENTITY values in a table variable for further consumption.
DECLARE #IDs TABLE(ID INT);
-- minor change to INSERT statement; add an OUTPUT clause:
INSERT dbo.foo(name)
OUTPUT inserted.ID INTO #IDs(ID)
SELECT N'Fred'
UNION ALL
SELECT N'Bob';
SELECT ID FROM #IDs;
The nice thing about this method is (a) it handles multi-row inserts (SCOPE_IDENTITY() only returns the last value) and (b) it avoids this parallelism bug, which can lead to wrong results, but so far is only fixed in SQL Server 2008 R2 SP1 CU5.
You can use:
SELECT IDENT_CURRENT('tablename')
to access the latest identity for a perticular table.
e.g. Considering following code:
INSERT INTO dbo.MyTable(columns....) VALUES(..........)
INSERT INTO dbo.YourTable(columns....) VALUES(..........)
SELECT IDENT_CURRENT('MyTable')
SELECT IDENT_CURRENT('YourTable')
This would yield to correct value for corresponding tables.
It returns the last IDENTITY value produced in a table, regardless of the connection that created the value, and regardless of the scope of the statement that produced the value.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.

SQL Server - Return value after INSERT

I'm trying to get a the key-value back after an INSERT-statement.
Example:
I've got a table with the attributes name and id. id is a generated value.
INSERT INTO table (name) VALUES('bob');
Now I want to get the id back in the same step. How is this done?
We're using Microsoft SQL Server 2008.
No need for a separate SELECT...
INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');
This works for non-IDENTITY columns (such as GUIDs) too
Use SCOPE_IDENTITY() to get the new ID value
INSERT INTO table (name) VALUES('bob');
SELECT SCOPE_IDENTITY()
http://msdn.microsoft.com/en-us/library/ms190315.aspx
INSERT INTO files (title) VALUES ('whatever');
SELECT * FROM files WHERE id = SCOPE_IDENTITY();
Is the safest bet since there is a known issue with OUTPUT Clause conflict on tables with triggers. Makes this quite unreliable as even if your table doesn't currently have any triggers - someone adding one down the line will break your application. Time Bomb sort of behaviour.
See msdn article for deeper explanation:
http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx
Entity Framework performs something similar to gbn's answer:
DECLARE #generated_keys table([Id] uniqueidentifier)
INSERT INTO Customers(FirstName)
OUTPUT inserted.CustomerID INTO #generated_keys
VALUES('bob');
SELECT t.[CustomerID]
FROM #generated_keys AS g
JOIN dbo.Customers AS t
ON g.Id = t.CustomerID
WHERE ##ROWCOUNT > 0
The output results are stored in a temporary table variable, and then selected back to the client. Have to be aware of the gotcha:
inserts can generate more than one row, so the variable can hold more than one row, so you can be returned more than one ID
I have no idea why EF would inner join the ephemeral table back to the real table (under what circumstances would the two not match).
But that's what EF does.
SQL Server 2008 or newer only. If it's 2005 then you're out of luck.
There are many ways to exit after insert
When you insert data into a table, you can use the OUTPUT clause to
return a copy of the data that’s been inserted into the table. The
OUTPUT clause takes two basic forms: OUTPUT and OUTPUT INTO. Use the
OUTPUT form if you want to return the data to the calling application.
Use the OUTPUT INTO form if you want to return the data to a table or
a table variable.
DECLARE #MyTableVar TABLE (id INT,NAME NVARCHAR(50));
INSERT INTO tableName
(
NAME,....
)OUTPUT INSERTED.id,INSERTED.Name INTO #MyTableVar
VALUES
(
'test',...
)
IDENT_CURRENT: It returns the last identity created for a particular table or view in any session.
SELECT IDENT_CURRENT('tableName') AS [IDENT_CURRENT]
SCOPE_IDENTITY: It returns the last identity from a same session and the same scope. A scope is a stored procedure/trigger etc.
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
##IDENTITY: It returns the last identity from the same session.
SELECT ##IDENTITY AS [##IDENTITY];
##IDENTITY Is a system function that returns the last-inserted identity value.
There are multiple ways to get the last inserted ID after insert command.
##IDENTITY : It returns the last Identity value generated on a Connection in current session, regardless of Table and the scope of statement that produced the value
SCOPE_IDENTITY(): It returns the last identity value generated by the insert statement in the current scope in the current connection regardless of the table.
IDENT_CURRENT(‘TABLENAME’) : It returns the last identity value generated on the specified table regardless of Any connection, session or scope. IDENT_CURRENT is not limited by scope and session; it is limited to a specified table.
Now it seems more difficult to decide which one will be exact match for my requirement.
I mostly prefer SCOPE_IDENTITY().
If you use select SCOPE_IDENTITY() along with TableName in insert statement, you will get the exact result as per your expectation.
Source : CodoBee
The best and most sure solution is using SCOPE_IDENTITY().
Just you have to get the scope identity after every insert and save it in a variable because you can call two insert in the same scope.
ident_current and ##identity may be they work but they are not safe scope. You can have issues in a big application
declare #duplicataId int
select #duplicataId = (SELECT SCOPE_IDENTITY())
More detail is here Microsoft docs
You can use scope_identity() to select the ID of the row you just inserted into a variable then just select whatever columns you want from that table where the id = the identity you got from scope_identity()
See here for the MSDN info http://msdn.microsoft.com/en-us/library/ms190315.aspx
Recommend to use SCOPE_IDENTITY() to get the new ID value, But NOT use "OUTPUT Inserted.ID"
If the insert statement throw exception, I except it throw it directly. But "OUTPUT Inserted.ID" will return 0, which maybe not as expected.
This is how I use OUTPUT INSERTED, when inserting to a table that uses ID as identity column in SQL Server:
'myConn is the ADO connection, RS a recordset and ID an integer
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())")
ID=RS(0)
You can append a select statement to your insert statement.
Integer myInt =
Insert into table1 (FName) values('Fred'); Select Scope_Identity();
This will return a value of the identity when executed scaler.
* Parameter order in the connection string is sometimes important. * The Provider parameter's location can break the recordset cursor after adding a row. We saw this behavior with the SQLOLEDB provider.
After a row is added, the row fields are not available, UNLESS the Provider is specified as the first parameter in the connection string. When the provider is anywhere in the connection string except as the first parameter, the newly inserted row fields are not available. When we moved the the Provider to the first parameter, the row fields magically appeared.
After doing an insert into a table with an identity column, you can reference ##IDENTITY to get the value:
http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx