SQL Server - Generate script without primary key - sql

I'm trying to make a generated script of my data (I mean, all the INSERT INTO commands).
Because access permissions, I can't do a SET IDENTITY_INSERT TABLE OFF and ON (I'm using the user application in Staging)
So, there is a way to make this script in SQL Server Manager and avoid the field with the primary key?
I set to false all properties (primary, unique, etc), but the script is still sending this field (For e.g., RecID 1, 2, 3, etc).
I'm using SQL Server 2012.
My configuration for the script:
Results I get:
SET IDENTITY_INSERT -TABLE- ON
INSERT INTO TABLE (ID,Field1) VALUES (1,'value')
Any solution (except for removing it with Notepad++) is appreciated.

A bit of a work around, but sometimes useful quick and dirty way of doing these things:
SELECT 'INSERT INTO TABLE (Field1) VALUES (''' + Field1 + ''')' FROM TABLE
The result set will be a row for each insert statement for every row in the table TABLE. The INSERT statement is generated from concatenating the INSERT statement text with the values in Field1.

There is another way to do this which is a bit more automatic and a lot less faffy when you have a lot of columns of different data types; given a table T:
(
ID int identity,
C1 nvarchar(255),
C2 datetime
...
)
...select everything except the identity column into a new table:
select C1, C2, ... into InterimTable from T
Then:
Run the Generate Scripts wizard on InterimTable.
Use whatever tool you have to search the SQL for InterimTable and replace with T
Run

Related

Inserting to one table, insert the ID to second table

Is it possible to populate a second table when I insert into the first table?
Insert post to table1 -> table 2 column recieves table1 post's unique id.
What I got so far, am I on the right track?
CONSTRAINT [FK_dbo.Statistics_dbo.News_News_NewsID] FOREIGN KEY ([News_NewsID]) REFERENCES [dbo].[News] ([NewsID])
Lots of ways:
an insert trigger
read SCOPE_IDENTITY() after the first insert, and use it to do a second
use the output clause to do an insert
Examples:
1:
create trigger Foo_Insert on Foo after insert
as
begin
set nocount on
insert Bar(fooid)
select id from inserted
end
go
insert Foo (Name)
values ('abc');
2:
insert Foo (Name)
values ('abc');
declare #id int = SCOPE_IDENTITY();
insert Bar(fooid)
select #id
3:
insert Bar(fooid)
select id from (
insert Foo (Name)
output inserted.id
values ('abc')) x
The only thing I can think of is that you can use a trigger to accomplish this. There is nothing "built in" to SQL Server that would do it. Why not just do it from your .NET code?
Yes it is, it sounds like you want a SQL Trigger, this would allow you to trigger logic based on actions on one table, to perform other actions in the DB. Here's another article on creating Simple SQL Triggers
SQL Server 2008 - Help writing simple INSERT Trigger
A Word of caution, this will do all the logic of updating the new table, outside of any C# code you write, it might sound nice to not have to manage it upfront, but you also lose control over when and if it happens.
So if you need to do something different later, now you have to update your regular code, as well as the trigger code. This type of logic can definitely grow, in large systems, and become a nightmare to maintain. Consider this, the alternative would be to build a method that adds the id to the new table after it inserts into the first table.
While i don't know what you're using to do your inserts assuming it's a SQL Command you can get back the ID on an identity column from the insert using Scope_Identity, found here
How to insert a record and return the newly created ID using a single SqlCommand?
if it's EF or some other ORM tool, they should either automatically update the entity, or have other mechanisms to deliver this data.

Find Last Inserted Record MS SQL SERVER

I applied 12Lac Insert command in Single table ,
but after some time query terminated , How can I find Last
Inserted Record
a)Table don't have created Date column
b)Can not apply order by clause because primary key values are manually generated
c)Last() is not buit in fumction in mssql.
Or any way to find last executed query
There will be some way but not able to figure out
Table contain only primary key constrain no other constrain
As per comment request here a quick and dirty manual solution, assuming you've got the list of INSERT statements (or the according data) in the same sequence as the issued INSERTs. For this example I assume 1 million records.
INSERT ... VALUES (1, ...)
...
INSERT ... VALUES (250000, ...)
...
INSERT ... VALUES (500000, ...)
...
INSERT ... VALUES (750000, ...)
...
INSERT ... VALUES (1000000, ...)
You just have to find the last PK, that has been inserted. Luckily in this case there is one. So you start doing a manual binary search in the table issuing
SELECT pk FROM myTable WHERE pk = 500000
If you get a row back, you know it got so far. Continue checking with pk = 750000. Then again, if it is there with pk = 875000. If 750000 is not there, then the INSERTs must have stopped earlier. Then check for pk = 675000. This process stops in this case after 20 steps.
It's just plain manual divide and conquer.
There is a way.
Unfortunately you have to do this in advance so it helps you.
So if you have, by any chance the PRIMARY KEYS you inserted, still at hand go ahead and delete all rows that have those keys:
DELETE FROM tableName WHERE ID IN (id1, id2, ...., idn)
Then you enable Change Data Capture for your database (have the db already selected):
EXEC sys.sp_cdc_enable_db;
Now you also need to enable Change Data Capture for that table, in an example that I've tried I could just run:
EXEC sys.sp_cdc_enable_table #source_schema = N'dbo', #source_name = N'tableName', #role_name = null
Now you are almost setup! You need to look into your system services and verify that SQL Server Agent is running for your DBMS, if it does not capturing will not happen.
Now when you insert something into your table you can select data changes from a new table called [cdc].[dbo_tableName_CT]:
SELECT [__$start_lsn]
,[__$end_lsn]
,[__$seqval]
,[__$operation]
,[__$update_mask]
,[ID]
,[Value]
FROM [cdc].[dbo_tableName_CT]
GO
An example output of this looks like this:
you can order by __$seqval that should give you the order in which the rows were inserted.
NOTE: this feature seems not to be present in SQL Server Express

Why is data table in VB 2010 and SQL Server starting with a negative primary key?

I defined a database using SQL Server 2008 R2 Express, and connected to it using Visual Basic 2010 Express. For some reason though, when I use the database in the program, it wants to start off using a negative primary key.
Is there any way to make the primary key only a positive number?
In addition to #RNarry Young response. You can check the schema if your table
Suppose you have the following table
create table #t
(
ID int Identity(-1, 1),
s varchar(100)
)
Now you make two inserts
Insert into #t(s) values('ed')
Insert into #t(s) values('ed')
Check the output
select * from #t
It shows like below. If you see the screen shot. The first row shows -1 in the primary key value. Due to the reason that the Identity Seed is -1 mentioned in the schema.
You can get rid of this issue. We should use the schema like below.
create table #t
(
ID int Identity(1, 1),
s varchar(100)
)
Following is the other way to generate
Set Identity_Insert #t On
Insert into #t(ID, s) values(-1, 'ed')
Set Identity_Insert #t OFF
Set Identity_Insert #t On
Insert into #t(ID, s) values(-2, 'ed')
Set Identity_Insert #t OFF
Off hand I can only think of two things that would cause this:
When creating the table you (or some software/code you are using) is setting the Identity seed to a negative number.
Or, you (or some software/code you are using) are using Identity_Insert and just forcing a negative number in.
The identity seed for the table will be visible within SSMS.
But.... it doesn't matter in the slightest that it's producing negative numbers. There's only really two practical concerns about your identiity value:
Unique values
Sufficient space to cover the expected range of values (so, a tinyint key wouldn't be great for tracking the entire world population...)
Once they're sorted, the actual values shouldn't be of any concern at all. They're internal to the database.

Asking a Microsoft SQL Server database for the next auto-generated identifier on a table

I have a table in a SQL Server database that has an auto-generated integer primary key. Without inserting a record into the table, I need to query the database and get what the next auto-generated ID number will be.
I think it's SQL Server version 2005, if that makes a difference.
Is there a way to do this?
Yes, but it's unreliable because another session might use the expected number.
If you still want to do this, use IDENT_CURRENT
Edit, as the comments have pointed out (improving my answer):
you need to add one IDENT_INCR('MyTable') to this to get the potential next number
another process may rollback and this number may not be the one used anyway
No, there is not. The ID will only ever be defined and handed out when the actual INSERT happens.
You can check the last given ID by using
DBCC CHECKIDENT('YourTableName')
but that's just the last one used - no guarantee that the next one is really going to be this value + 1 - it could be - but no guarantees
The only way to get a number that is guranteed not to be used by another process (i.e., a race condition) is to do the insert - is there any reason you can't do a NULL insert (i.e., just insert into the table with NULLs or default values for all other columns) and then subsequently UPDATE it?
i.e.,
CREATE TABLE bob (
seq INTEGER IDENTITY (1,1) NOT NULL,
col1 INTEGER NULL
)
GO
DECLARE #seqid INTEGER
INSERT INTO bob DEFAULT VALUES
SET #seqid = SCOPE_IDENTITY()
-- do stuff with #seqid
UPDATE bob SET col1 = 42 WHERE seq = #seqid
GO
You shouldn't use the technique in code, but if you need to do it for investigative purposes:
select ident_current(‘foo’) + ident_incr(‘foo’)
That gives you the last value generated + the incrementation for the identity, so should represent the next choice SQL would make without inserting a row to find out. This is a correct value even if a rollback has pushed the value forwards - but again, this is investigative SQL not stuff I would put in code.
The two values can also be found in the sys.identity_values DMV, the fields are increment_value and last_value.
Another way, depending on what your doing, is inserting whatever data goes into the table, and then using ##identity to retrieve the id of the record inserted.
example:
declare #table table (id int identity(1,1), name nvarchar(10))
insert into #table values ('a')
insert into #table values ('b')
insert into #table values ('c')
insert into #table values ('d')
select ##identity
insert into #table values ('e')
insert into #table values ('f')
select ##identity
This is pretty much a bad idea straight off the bat, but if you don't anticipate high volume and/or concurrency issues, you could just do something like this
select #nextnum = max(Id) + 1 from MyTable
I don't think thats possible out of the box in MS SQL (any version). You can do this with column type uniqueidentifier and using function NEWID().
For int column, you would have to implement your own sequential generator.

Share auto-incremented primary key between two tables

Hi I want to have two tables each have an INT "id" column which will auto-increment but I don't want either "id" columns to ever share the same number. What is this called and what's the best way to do it? Sequence? Iterator? Index? Incrementor?
Motivation: we're migrating from one schema to a another and have a web-page that reads both tables and shows the (int) ID, but I can't have the same ID used for both tables.
I'm using SQL Server 9.0.3068.
Thanks!
Just configure the identity increment to be >1 e.g. table one uses IDENTITY (1, 10) [1,11,21...] and table two uses IDENTITY (2, 10) [2,12,22...]. This will also give you some room for expansion if needed later.
I think using a GUID would be the most straightforward way, if I understand you correctly.
SELECT NEWID()
Use a column with GUID (Globally Unique Identifier) type. It's 16 byte and will be always unique for each row.
Just be aware that you'll get a significant performance hit comparing to normal integer keys.
Use another table with an ID key of type int default it to 1, called KeyID or whatever.
Have a stored procedure retrieve the value, add 1, then update the KeyID, then return this to the stored procedure which is updating your two tables which needs the new unique key.
This will ensure the ID is an int, and that it's unique between the set of tables which are using the stored procedure to generate new ID's.
You can define an IDENTITY column in a third table, use that to generate ID values, but you always roll back any inserts you make into the table (to avoid making it grow). Rolling back the transaction doesn't roll back the fact that the ID was generated.
I'm not a regular user of Microsoft SQL Server, so please forgive any syntax gaffes. But something like the following is what I have in mind:
CREATE TABLE AlwaysRollback (
id IDENTITY(1,1)
);
BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;
INSERT INTO RealTable1 (id, ...) VALUES (SCOPE_IDENTITY(), ...);
BEGIN TRANSACTION;
INSERT INTO AllwaysRollBack () VALUES ();
ROLLBACK TRANSACTION;
INSERT INTO RealTable2 (id, ...) VALUES (SCOPE_IDENTITY(), ...);
I don't know what you would call it.
If you don't want to use a GUID or a separate table, you could also create a function that looked at the max values of the ids from both tables and added one to the that value (or something like that).
You could then call that function in an insert trigger on both tables.
I am personally a fan of the GUID solution, but here is a viable option.
Many solutions to this problem have avoided GUID and used good old integer. This is common also with merge replication situations where many satellite sites merge with a master and key conflicts need to be avoided.
If GUID will not work for you, and you absolutely must have int, bigint, or the like, you can always just use an IDENTITY column and have each table with a different value for SEED. Those datatypes have a very wide range, and it is not too hard to split the range into usable segments, especially if all you want is two splits. As an example, basic int has a range from -2^31 (-2,147,483,648) through 2^31 - 1 (2,147,483,647). This is more than enough for a customer table, for example.
Transact-SQL Reference (SQL Server 2000)
int, bigint, smallint, and tinyint
Example:
--Create table with a seed of 1 billion and an increment of 1
CREATE TABLE myTable
(
primaryKey int IDENTITY (1000000000, 1),
columnOne varchar(10) NOT NULL
)
If you really need to do this with an int and you have an auto incrementing number, the way i have done this before is to change the id field auto increment function to the sequence of the other table. I am not too sure in ms sql or my sql but in pgsql that means that in the sql you would have this field
id integer NOT NULL DEFAULT nextval('table_two_seq'::regclass),
where table_two_sequence is the sequence function for the other table. Then test it out by inserting some data. I am really sorry if this wont work in ms sql i try to steer clear of it tbh. Failing that the GUID is the best way as has been mentioned by others. Or when inserting in the code that you use you could put an algorithm in that but it could get messy.
Alternatively, think about having the data in one table as this would be a way around it. if you need to you could have a view simulating two tables. Just a thought.
Hope i have helped
Starting with SQL Server 2012 you can declare a sequence object
https://msdn.microsoft.com/en-us/library/ff878091.aspx which is exactly what you need.
I should be pretty trivial to emulate a sequence object with a table
containing the next sequence value and a stored procedure atomically
select the value and increment. [You'd liked to use function, but functions
can't have side effects.]
How about this hack? Create a table (MySequence) with two columns: And Identity column (SequenceValue) and a dummy column (DummyValue) and use this stored procedure to get a new sequence value. The only row in the table will be last sequence value retrieved.
CREATE PROCEDURE GetNextValue
AS
BEGIN
DECLARE #value int = null;
-- Insert statements for procedure here
INSERT into MySequence (DummyValue) Values (null);
SET #value = SCOPE_IDENTITY();
DELETE from MySequence where SequenceValue <> #value
SELECT #value as Sequence
return #value
END
To use the sequence you'd have to manage the inserts to the target tables--a trigger would probably work.