I am trying to create a sequence with a table MiCliente the sequence must be eliminate if this exist, must be one by one and with a cycle and it needs to start with 1000. I need to associate the sequence with a column MiCliente.idCliente.
CREATE TABLE dbo.MiCliente
(
idCliente int NOT NULL,
idMunicipio int NOT NULL,
cedula varchar(20) NOT NULL,
nombres varchar(100) NOT NULL,
apellidos varchar(100) NOT NULL,
idSexo char(1) NULL,
idEstadoCivil tinyint NULL,
fechaNacimiento date NULL,
telefono varchar(20) NULL,
celular varchar(20) NULL,
direccion varchar(100) NULL,
email varchar(100) NULL
);
GO
Create Sequence Conteo
AS tinyint
START WITH 1000
INCREMENT BY 1
GO
When I execute the query I receive
error 343
I think maybe an identity field would solve your problem best. You can't really associate a sequence with a table field; at least not by definition. A sequence can be used as a type of "counter" object and can be invoked for a table to generate a value that gets inserted into a table.
(here is a good discussion on using sequences:
https://www.simple-talk.com/sql/learn-sql-server/sql-server-sequence-basics/)
For example, using the sequence you created in your example (keep in mind, as ZLK comments, tinyint is for values from 0 to 255; you should use int) one could say:
select (next value for Conteo) idCliente, cedula, email from dbo.MiCliente;
or something like
INSERT INTO MiCliente
(idCliente, idMunicipio, cedula, nombres, apellidos)
VALUES
(NEXT VALUE FOR Conteo, 1,'test','Smith','test2');
So this works, but one could reference the same sequence for another table as well. So it isn't specifically "tied" to your table. It may not matter though.
On the other hand, you could set idCliente as an identity field such that it also begins with 1000. This is "tied" to the table and, in my opinion, is easier to use. The number just get generated automatically.
So you might do something like:
Alter table dbo.MiCliente add idCliente INT IDENTITY(1000,1)
And then you can make it your primary key as well:
alter table dbo.MiCliente add constraint PK_MiCliente PRIMARY KEY(idCliente)
When I executed your query it simply gives following error:
Msg 11708, Level 16, State 1, Line 2
An invalid value was specified for argument 'START WITH' for the given data type.
It is clearly evident of the fact that you are using wrong data type tinyint while creating the sequence. Changing it to int should solve your problem. Here is the modified query. Hope this helps!
Create Sequence Conteo
AS int
START WITH 1000
INCREMENT BY 1
GO
I was able to create the sequence successfully after making this change. I'm on SQL Server 2012.
Related
I have a couple tables with a view that joins them
CREATE TABLE Valve (
ValveID int IDENTITY NOT NULL,
ValveName varchar(100) NOT NULL,
ValveOwner varchar(100) NOT NULL
)
CREATE TABLE ValveRecording (
ValveID int IDENTITY NOT NULL,
Date date NOT NULL,
Measure varchar(100) NOT NULL,
Value numeric NOT NULL
)
ALTER VIEW ValveRecordingView
AS
SELECT
v.ValveName,
v.ValveOwner,
vr.Measure,
vr.Value
FROM Valve v
LEFT OUTER JOIN ValveRecording vr on v.ValveID = vr.ValveID
*Note above was just typed in - so may have errors.
The problem with the view is that if queried for a date range where no measurement was made,
there is no row present for the measure-value pair. I would like to
restate the view in a way that some value is returned for each date-measure-value tuples.
If one wasn't present then return a zero.
I think that it's possible, but the SQL is a bit beyond me. I assume
that it involves a UNION ALL with a query that gets date-measure-value
tuples which aren't already present. Probably an ugly query but that's
okay.
I have a table with this structure:
CREATE TABLE [dbo].[cl](
[ID] [int] IDENTITY(1,1) NOT NULL,
[NIF] [numeric](9, 0) NOT NULL,
[Name] [varchar](80) NOT NULL,
[Address] [varchar](100) NULL,
[City] [varchar](40) NULL,
[State] [varchar](30) NULL,
[Country] [varchar](25) NULL,
Primary Key([ID],[NIF])
);
Imagine that this table has 3 records. Record 1, 2, 3...
When ever I delete Record number 2 the IDENTITY Field generates a Gap. The table then has Record 1 and Record 3. Its not correct!
Even if I use:
DBCC CHECKIDENT('cl', RESEED, 0)
It does not solve my problem becuase it will set the ID of the next inserted record to 1. And that's not correct either because the table will then have a multiple ID.
Does anyone has a clue about this?
No database is going to reseed or recalculate an auto-incremented field/identity to use values in between ids as in your example. This is impractical on many levels, but some examples may be:
Integrity - since a re-used id could mean records in other systems are referring to an old value when the new value is saved
Performance - trying to find the lowest gap for each value inserted
In MySQL, this is not really happening either (at least in InnoDB or MyISAM - are you using something different?). In InnoDB, the behavior is identical to SQL Server where the counter is managed outside of the table, so deleted values or rolled back transactions leave gaps between last value and next insert. In MyISAM, the value is calculated at time of insertion instead of managed through an external counter. This calculation is what is giving the perception of being recalcated - it's just never calculated until actually needed (MAX(Id) + 1). Even this won't insert inside gaps (like the id = 2 in your example).
Many people will argue if you need to use these gaps, then there is something that could be improved in your data model. You shouldn't ever need to worry about these gaps.
If you insist on using those gaps, your fastest method would be to log deletes in a separate table, then use an INSTEAD OF INSERT trigger to perform the inserts with your intended keys by first looking for records in these deletions table to re-use (then deleting them to prevent re-use) and then using the MAX(Id) + 1 for any additional rows to insert.
I guess what you want is something like this:
create table dbo.cl
(
SurrogateKey int identity(1, 1)
primary key
not null,
ID int not null,
NIF numeric(9, 0) not null,
Name varchar(80) not null,
Address varchar(100) null,
City varchar(40) null,
State varchar(30) null,
Country varchar(25) null,
unique (ID, NIF)
)
go
I added a surrogate key so you'll have the best of both worlds. Now you just need a trigger on the table to "adjust" the ID whenever some prior ID gets deleted:
create trigger tr_on_cl_for_auto_increment on dbo.cl
after delete, update
as
begin
update dbo.cl
set ID = d.New_ID
from dbo.cl as c
inner join (
select c2.SurrogateKey,
row_number() over (order by c2.SurrogateKey asc) as New_ID
from dbo.cl as c2
) as d
on c.SurrogateKey = d.SurrogateKey
end
go
Of course this solution also implies that you'll have to ensure (whenever you insert a new record) that you check for yourself which ID to insert next.
I got an error from the insert statement.
The statement that I used to insert a tuple into the table is
insert into train values (103, MH380, 2000, 709)
By the way, the table was created by using the statement below:
(
TrainCode CHAR(5) NOT NULL,
TrainName VARCHAR(20) NOT NULL,
Capacity int NOT NULL,
Model VARCHAR(20) NOT NULL,
CONSTRAINT PKTrain PRIMARY KEY (TrainCode)
)
Can someone please help? TQ
MH380 appears to be a string, so you need to surround it in single quotes.
insert into train values (103, 'MH380', 2000, 709)
You may also want to check the other values too - they appear numeric but if you've declared their corresponding column types as chars or varchars (e.g. the train code?), you should really cast them as such by putting quotes around them too.
Also you might want to think about putting your column names into your INSERT statement, so the order of fields is explicit rather than implicit. Could save headaches later if your table gets altered!
Per your posted table structure as below
(TrainCode CHAR(5) NOT NULL, TrainName VARCHAR(20) NOT NULL, Capacity int
NOT NULL,Model VARCHAR(20) NOT NULL, CONSTRAINT PKTrain PRIMARY KEY (TrainCode) )
Correct INSERT statement should be like below since except Capacity all other columns are of VARCHAR type.
insert into train values ('103', 'MH380', 2000, '709')
With the table specified below, how could I modify the locking behavior in SQL Server 2012 to block statements and transactions attempting to select data pertaining to a specific UserId column?
I have been attempting to come up with a stored procedure that will successfully change an address for a specific user. In order to do this, the existing record is marked as deleted by setting DeletedOn to the current date. Afterward, the new record is inserted. I do not want any queries to be able to see that no valid address is present for the given user in the table between the deletion mark and the insertion.
Queries related to a different user's address should be able to complete, so long as that user's address is not in the process of being modified.
CREATE TABLE [Address]
(
[Id] BIGINT NOT NULL,
[UserId] FOREIGN KEY REFERENCES [User]([Id]) NOT NULL,
[House] CHARACTER VARYING(255) NOT NULL,
[Street] CHARACTER VARYING(255) NOT NULL,
[City] CHARACTER VARYING (255) NOT NULL,
[State] CHARACTER VARYING(255) NOT NULL,
[Zip] CHARACTER VARYING(15) NOT NULL,
[CreatedOn] DATETIMEOFFSET NOT NULL,
[DeletedOn] DATETIMEOFFSET NULL,
UNIQUE([UserId], [DeletedOn]),
CHECK(([DeletedOn] IS NULL) OR ([CreatedOn] <= [DeletedOn])),
PRIMARY KEY([Id])
);
Using a history table solved this issue. It seems that UNIQUE constraints cause lots of lock escalations when they are defined as composites.
The history table now tracks all of the old versions of a particular record and history inserts are combined with live table updates in a repeatable read transaction.
What do you know, I was approaching the whole problem the wrong way!
I want a bigint ID column for every row of data that i insert into a table. I want Sql server to generate the numbers. I tried to create a table with a bigint column ID. I want this to be autoincrement with the first value as 1. I tried using [ID] [bigint] AUTO_INCREMENT NOT NULL, in my create table statement, but I got the error - Incorrect syntax near 'AUTO_INCREMENT'. How do I do this ?
Can you not just declare it as an IDENTITY column:
[ID] [bigint] IDENTITY(1,1) NOT NULL;
The 1,1 refers to the start index and the amount it is being incremented by.
NOTE: You do not have to provide a value for the ID column when you do an insert. It will automatically choose it. You can modify these values later if required.
EDIT:
Alternatively, you can use a stored procedure to handle all the inserts.
Example:
Stored Procedure will take in variables as you would a normal insert (one variable for every column). The logic within the stored procedure can select the max value currently existing in the table and choose that as its max value.
DECLARE #yourVariable = SELECT MAX(ID) FROM YourTable
Use #yourVariable as your insert value. You can increment it or change value as necessary.
I got the answer here - http://www.sqlservercentral.com/Forums/Topic1512425-149-1.aspx
CREATE TABLE Test (
ID BIGINT IDENTITY NOT NULL,
SomeOtherColumn char(1)
)
INSERT INTO Test (SomeOtherColumn)
values ('a')