Getting negative autoincrement value in Delphi CE against Sqlite3 - database

I have looked and maybe I don't know where to look, but here is my situation. I converted a working .mdb database to SQlite using a trial app: ESF Database Migration Toolkit. I migrated all the data with a last autoincremented ID of 263. When I tried to insert any data into the .db using Delphi CE, the autoincrement field didn't work, saying the ID field needed a value. I looked at the table and it had a constraint for the field. I removed the constraint using SQliteUI, redid the ID making it a PRIMARY KEY NOT NULL AUTOINCREMENT and now can add data, but it gives me a negative ID (-3). If I put this in SQLiteUI directly it gives a NULL value until the table is refreshed and I get the correct next ID (264). What could I be doing wrong? Should I have not migrated with data? Remade the table in SQLiteUI? I didn't want to have to manually reenter all that data. Thanks
CREATE TABLE wines (
wineID INTEGER PRIMARY KEY ASC AUTOINCREMENT NOT NULL,
winename VARCHAR (175),
winery VARCHAR (200),
varietal VARCHAR (200),
winetype VARCHAR (150),
incellar INTEGER DEFAULT 0,
vintage VARCHAR (10),
grapes VARCHAR (150),
pricepaid NUMERIC (10, 2) DEFAULT 0,
winelabel BLOB,
wherestored VARCHAR (100),
rating VARCHAR (10),
datepurchased DATETIME,
foodpairing VARCHAR (255),
region VARCHAR (150),
regionalstyle VARCHAR (150),
country VARCHAR (150),
mynotes VARCHAR (255)
)

Related

SQL creating and populating

Could anyone experienced have a quick look at the following. I am not smart enough to resolve the system error just yet.
CREATE TABLE TestSubject (
test_subjectID NCHAR (6) NOT NULL PRIMARY KEY,
subject_name NVARCHAR (10) NOT NULL,
subject_address NVARCHAR (12) NOT NULL,
)
;
CREATE TABLE PhNumber (
subject_id NCHAR (6) NOT NULL,
ph_number NVARCHAR (20) NOT NULL,
PRIMARY KEY (ph_number),
FOREIGN KEY (subject_id) REFERENCES TestSubject (test_subjectID)
);
CREATE TABLE Test (
test_date DATETIME NOT NULL,
subject_id NCHAR (6) NOT NULL,
result NVARCHAR (10),
PRIMARY KEY (test_date),
FOREIGN KEY (subject_id) REFERENCES TestSubject (test_subjectID));
CREATE TABLE Place (
place_name NVARCHAR (10) NOT NULL PRIMARY KEY,
place_address NVARCHAR (8),
place_owner NVARCHAR (8)
);
CREATE TABLE VisitSubject (
v_date DATETIME NOT NULL,
v_number NVARCHAR (20) NOT NULL,
place_visit NVARCHAR (10) NOT NULL,
party_size INT,
PRIMARY KEY (v_date),
FOREIGN KEY (v_number) REFERENCES PhNumber (ph_number),
FOREIGN KEY (place_visit) REFERENCES Place (place_name));
And the populate script
INSERT INTO TestSubject
VALUES
('S001', 'Daniel Doppler', '5 Beetle Avenue Aberdeen'),
('S002', 'Florence West', '17 Green Crescent Dundee'),
('S003', 'Werner Flick', '25A Grubb Street Stonehaven'),
('S004', 'Tiffany Smith', '11 Green Crescent Dundee'),
('S005', 'Angela Ashe', '113 Wasp Street Aberdeen');
INSERT INTO Test
VALUES
('2020/08/05 00:00:00', 'S001', 'Negative'),
('2020/08/10 00:00:00', 'S002', 'Positive'),
('2020/08/17 00:00:00', 'S003', 'Negative'),
('2020/08/22 00:00:00', 'S004', 'Negative'),
('2020/08/22 00:00:00', 'S005', 'Negative'),
('2020/09/03 00:00:00', 'S001', 'Positive');
INSERT INTO PhNumber
VALUES
('S001', '07123-123456'),
('S002', '07777-111000'),
('S003', '07555-246810'),
('S004', '07101-484848'),
('S004', '07896-102304'),
('S005', '07777-534242');
INSERT INTO Place
VALUES
('Pink Lion Inn', 'Forfar', 'Sean Conran'),
('Irenes Hair Salon', 'Stonehaven', 'Irene Jones');
INSERT INTO VisitSubject
VALUES
('2020/08/01 00:00:00', '07123-123456', 'Irenes Hair Salon', '1'),
('2020/08/01 00:00:00', '07777-111000', 'Irenes Hair Salon', '2'),
('2020/08/25 00:00:00', '07123-123456', 'Pink Lion Inn', '4'),
('2020/08/25 00:00:00', '07493-285113', 'Pink Lion Inn', '2'),
('2020/09/10 00:00:00', '07555-246810', 'Irenes Hair Salon', '1'),
('2020/09/15 00:00:00', '07555-246810', 'Pink Lion Inn', '3');
I cannot populate the existing tables because of 2 errors -
String or binary data would be truncated
and
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Test__subject_id__286302EC". The conflict occurred in database "TAT_2012552", table "dbo.TestSubject", column 'test_subjectID'.
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__PhNumber__subjec__25869641". The conflict occurred in database "TAT_2012552", table "dbo.TestSubject", column 'test_subjectID'.
The first error means that you are trying to insert a value in a column where the data type length is smaller than the value. For example, in your VisitSubject table, the place_visit column can accept strings that have 10 characters or less. In your case, for example, value Irenes Hair Salon cannot be inserted because it's more than 10 characters.
The second error is thrown because subject_id values inserted in your tables Test and PhNumber are not existing in the table TestSubject. And why it is not existing in your table TestSubject ? Because SQL couldn't insert any row in this table because subject_name and subject_address values inserted have more characters than the data type length defined in your table.
Please first solve issue about inserting values longer than the data types definitions, and it should solve your foreign key issues then.
Let's start with the obvious error:
String or binary data would be truncated
This error is very much telling you the problem, you have a string value that is trying to be inserted into a column, however, it is too large and as such the value would be truncated. As a result the INSERT statement fails. If you're on a more recent version of SQL Server, you actually get even more verbose errors for this. There are actually 3 of these errors in your batch, such as:
String or binary data would be truncated in table 'YourDatabase.dbo.TestSubject', column 'subject_name'. Truncated value: 'Daniel Dop'.
Clearly you aren't using the latest version of SQL Server, or you would have shared that whole error, however, the old error do still tell you what table and column the error is on.
So let's have a look at the column YourDatabase.dbo.TestSubject.subject_name, which is defined as a nvarchar(10). Well looking at the INSERT, the first person's name is 'Daniel Doppler', which is more than 10 characters and hence the error. In fact, the entire INSERT statement will fail for every string value, as your subject_address column is defined as an nvarchar(12), yet the first value you try to INSERT is '5 Beetle Avenue Aberdeen' which is way more than 12 characters.
So how do you fix this? Fix your table's definition and increase the size of the columns; clearly 10 and 12 characters are not enough for a "subject's" name and address respectively.
So, what about the other errors such as:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Test__subject_id__29572725". The conflict occurred in database "YourDatabase", table "dbo.TestSubject", column 'test_subjectID'.
Well, this is actually a result of your prior error; your INSERT failed as you're trying to INSERT data that is too large for your columns and thus it isn't INSERTed. Then, when you get to the next INSERT statement the Foreign Key constraint (which has an obtuse name as you didn't give it one, but we'll come to that in a second) fails it's CHECK as there are no rows in the table dbo.TestSubject. Effectively the prior truncation error just compounds the problem.
As I mentioned, these errors happen multiple times, you have 3 truncation errors in that batch; meaning 3 INSERT statements fail due to the column being too small for the value to fit; you'll need to fix each of those tables definition so that they are an appropriate length for the data you are inserting. You also have 2 Foreign Key constrait failures, but these will likely disappear when you fix the table definitions.
As I mentioned, I do, however, recommend naming your constraints. You can do this by using an ALTER statement and creating the CONSTRAINT in there instead. For example:
CREATE TABLE dbo.PhNumber (subject_id nchar(6) NOT NULL,
ph_number nvarchar(20) NOT NULL);
ALTER TABLE dbo.PhNumber ADD CONSTRAINT PK_PhNumber PRIMARY KEY CLUSTERED (ph_number);
ALTER TABLE dbo.PhNumber ADD CONSTRAINT FK_PhNumber_TestSubject FOREIGN KEY (subject_id) REFERENCES dbo.TestSubject (test_subjectID);
This changes one the errors, about the Foreign Key failure, to the below; which is must more understandable due to the key's name:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_PhNumber_TestSubject". The conflict occurred in database "YourDatabase", table "dbo.TestSubject", column 'test_subjectID'.

How can add UNIQUE column to a table in a SQL Server database?

I need UNIQUE column in my table.
My table:
CREATE TABLE my_table
(
id int IDENTITY PRIMARY KEY,
name text NOT NULL UNIQUE,
blabla text NOT NULL
);
and I get an error:
Column 'name' in table 'my_table' is of a type that is invalid for
use as a key column in an index. Could not create constraint or index.
See previous errors.
So, How can add UNIQUE column in table?
You should be using VARCHAR / NVARCHAR instead of TEXT, because TEXT data type is deprecated - see https://msdn.microsoft.com/en-us/library/ms187993.aspx
CREATE TABLE my_table
(
id int IDENTITY PRIMARY KEY,
name VARCHAR(100) NOT NULL CONSTRAINT UQ_my_table_name UNIQUE,
blabla VARCHAR(100) NOT NULL
);
Also, consider naming your constraints rather than let a default name for it.
So the problem lies with the data type you have specified for column name. Essentially 'text' is a large object (LOB) data type. SQL does not allow the creation of index over this particular data type. Other examples of such a data type would be varchar(max), nvarchar(max), varbinary(max), xml, and image.
I believe it is largely because these are not allocated any specific data size from the beginning and hence any index created would have to be changed if it's maximum limit is surpassed.
https://msdn.microsoft.com/en-us/library/ms188783.aspx

Sql Server row size limit and table design

I have this query on SQL Server 2008
CREATE TABLE MediaLibrary
(
MediaId bigint NOT NULL IDENTITY (1, 1),
MediaTypeId smallint NOT NULL,
ImageNameByUser nchar(100) NULL,
GeneratedName uniqueidentifier NOT NULL,
UploadedByUserId uniqueidentifier NOT NULL,
UploadedDate date NOT NULL,
ProfilePhoto bit NOT NULL,
PublicPhoto bit NOT NULL,
AppointmentId bigint NULL,
OriginalImage nchar(1000) NULL,
ThumbImage nchar(1000) NULL,
MediumImage nchar(1000) NULL,
LargeImage nchar(1000) NULL,
UrlThumb nchar(1000) NULL,
UrlMedium nchar(1000) NULL,
UrlLarge nchar(1000) NULL,
InactiveReasonId smallint NULL,
InactiveDate datetime NULL
) ON [PRIMARY]
GO
When I attempt to create the table I get this error
Creating or altering table 'MediaLibrary' failed because the minimum row size would be 14273, including 9 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.
I get that I am hitting the limit on row size, but this is not a big table so I am wondering if this is not a good design?
When I changed the nchar(1000) to varChar(1000) the table saved fine. My concern is that once data is actually getting saved into the table that I will hit the row size limit again.
Assuming you're not going to populate all columns, you need to use nvarchar (or just varchar) and not nchar (or char). The reason is that an nchar(1000) needs to reserve 2000 bytes, whether you're going to use it or not. This isn't true for varchar/nvarchar.
Now, if you are going to potentially have 1000 characters in each of these columns, it's not going to work no matter what data type you use. The reason is that the fundamental storage element in SQL Server is an 8K page. So it's not possible to store a row with more than ~8K (there is some page header overhead as well as other bits that may be used depending on data types in the column). The workarounds are typically to:
varchar(max) - which can store data that doesn't fit off-row as a blob, but there is a performance overhead for this, and it can introduce some limitations, e.g. the ability to perform online rebuilds
change the table structure, so that these URLs are stored as separate rows in a separate table. Example:
CREATE TABLE dbo.Media
(
MediaID BIGINT IDENTITY(1,1) PRIMARY KEY,
MediaTypeID SMALLINT NOT NULL,
ImageNameByUser NVARCHAR(100) NULL, -- should also not be nchar
GeneratedName UNIQUEIDENTIFIER NOT NULL,
UploadedByUserId UNIQUEIDENTIFIER NOT NULL,
UploadedDate date NOT NULL,
ProfilePhoto bit NOT NULL,
PublicPhoto bit NOT NULL,
AppointmentId bigint NULL,
InactiveReasonId smallint NULL,
InactiveDate datetime NULL
);
CREATE TABLE dbo.URLTypes
(
URLTypeID TINYINT NOT NULL PRIMARY KEY,
Description NVARCHAR(32) NOT NULL UNIQUE
);
INSERT dbo.URLTypes VALUES(1,'OriginalImage'),(2,'ThumbImage'),...;
CREATE TABLE dbo.MediaURLs
(
MediaID BIGINT NOT NULL FOREIGN KEY REFERENCES dbo.Media(MediaID),
URLTypeID TINYINT NOT NULL FOREIGN KEY REFERENCES dbo.URLTypes(URLTypeID),
URL VARCHAR(2048) NOT NULL
);
As an aside, are you really going to need to support Unicode for URLs?
I was facing a similar issue with a small table, no more than 7 fields, and all of them Integer.
It turns out that the developers found out that it was faster to drop and recreate one of the columns (to reset the value of that table) than updating the value for all of the rows.
So when the column was recreated too much times, it will trigger that error:
Creating or altering table 'TableName' failed because the minimum row size would be XX, including X bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.
The solution was to run
ALTER TABLE [TableName] REBUILD
I hope this helps someone

How can I add a timestamp column to my SQL Server table when I create it?

I am trying to use the following:
CREATE TABLE [dbo].[Application] (
[ApplicationId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
timestamp
CONSTRAINT [PK_dbo.Application] PRIMARY KEY CLUSTERED ([ApplicationId] ASC)
);
Can someone confirm if this is the correct way. Also can or should I give that column a name of its own?
* Note that I am using Entity Framework. So is it okay to add a column like this but to not add it to the Application object?
I think that timestamp is a poor name for that datatype (it does not store time) and somewhere along the way Microsoft did too and has deprecated the use of timestamp since SQL Server 2008 in favor of rowversion introduced in SQL Server 2000.
Your code uses a behavior of timestamp that it gives the column a default name, rowversion does not do that so you have to give the column a name.
CREATE TABLE [dbo].[Application] (
[ApplicationId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
VerCol rowversion
CONSTRAINT [PK_dbo.Application] PRIMARY KEY CLUSTERED ([ApplicationId] ASC)
);
Ref:
rowversion (Transact-SQL)
timestamp SQL Server 2000
* Note that I know nothing about using Entity Framework.
CREATE TABLE [dbo].[Application] (
[ApplicationId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
timestamp DATETIME NULL DEFAULT GETDATE()
CONSTRAINT [PK_dbo.Application] PRIMARY KEY CLUSTERED ([ApplicationId] ASC)
);
To add the timestamp / rowversion to an existing table you can do this.
ALTER Table OrderAction ADD [RowVersion] rowversion not null
It will automatically assign timestamps, you don't need to anything like UPDATE rowversion = getdate()
Please note that if your table is large it can take a while since it needs to add a timestamp for every row. If you have a huge table and you're using a scalable database like Azure SQL you might want to increase capacity first and/or do it during off hours.
timestamp data type is identical to rowversion datatype - it's just up to you what you call the column.
It also doesn't need to be in your data model to be updated by an UPDATE or INSERT. However if it isn't in your data model then you won't actually benefit from the whole point of it which is to get a simplified UPDATE like this:
WHERE ([OrderId] = #p0) AND ([RowVersion] = #p1)

Multiple timestamp columns in SQL Server 2000

I need to create a table in SQL Server 2000.
create table TABLE (
DBID_ bigint not null,
CLASS_ varchar(255) not null,
DBVERSION_ integer not null,
HPROCI_ bigint,
TYPE_ varchar(255),
EXECUTION_ varchar(255),
ACTIVITY_NAME_ varchar(255),
START_ timestamp,
END_ timestamp,
DURATION_ bigint,
TRANSITION_ varchar(255),
NEXTIDX_ integer,
HTASK_ bigint,
primary key (DBID_)
);
An error occurs when I run it.
A table can only have one timestamp column. Because table TABLE
already has one, the column END_ cannot be added.
What is the best alternative for timestamp for SQL Server? How to fix this issue?
A timestamp is not a datetime datatype as the name suggests. It is an internal value that is relative to the server's clock, but an actual time cannot be derived from it's value. It is simply used to evaluate whether a row has been updated, and thus a table can only have one column of this type. The timestamp syntax is actually deprecated and is now named rowversion which makes a lot more sense.
Given your column names (Start, End) I assume you are trying to store actual timestamps, and should instead be using datetime as your datatype.
In Sql Server timestamp is a data type and it's not a time.
It's basically a way of versioning a record and it's used for optimistic locking in a disconnected database model
When you load up the record, you pick up the timestamp column. You only write it back if the value in the timestamp column is the same, as that means no one else has changed it since you got it.
If you want a real datetime value, add a datetime either not null, or with a default of GetDate() and remember to update every update.

Resources