As an alternative to anti-patterns like Entity-Attribute-Value or Key-Value Pair tables, is it possible to dynamically add columns to a data table via an INSERT trigger on a parameter table?
Here would be my tables:
CREATE TABLE [Parameters]
(
id int NOT NULL
IDENTITY(1,1)
PRIMARY KEY,
Parameter varchar(200) NOT NULL,
Type varchar(200) NOT NULL
)
GO
CREATE TABLE [Data]
(
id int NOT NULL
IDENTITY(1,1)
PRIMARY KEY,
SerialNumber int NOT NULL
)
GO
And the trigger would then be placed on the parameter table, triggered by new parameters being added:
CREATE TRIGGER [TRG_Data_Insert]
ON [Parameters]
FOR INSERT
AS BEGIN
-- The trigger takes the newly inserted parameter
-- record and ADDs a column to the data table, using
-- the parameter name as the column name, the data type
-- as the column data type and makes the new column
-- nullable.
END
GO
This would allow my data mining application to get a list of parameters to mine and have a place to store that data once it mines it. It would also allow a user to add new parameters to mine dynamically, without having to mess with SQL.
Is this possible? And if so, how would you go about doing it?
I think the idea of dynamically adding columns will be a ticking time bomb, just gradually creeping towards one of the SQL Server limits.
You will also be putting the database design in the hands of your users, leaving you at the mercy of their naming conventions and crazy ideas.
So while it is possible, is it better than an EAV table, which is at least obvious to the next developer to pick up your program؟
Related
I've created a new table and made column id the primary key and defined it as uniqueidentifier.
Is there a way during the tables design in SQL Server Management Studio to assign a rule that all new rows auto generate a new uniqueidentifier in the id column?
At the moment to make my form (made on Retool) write to the table I need to type out a random set of characters, essentially self creating my own uniqueidentifier which obviously isn't correct.
Avoid the designers, they've been a complete and utter mess for 17 years. Do this in a query window:
USE tempdb;
GO
CREATE TABLE dbo.what
(
id uniqueidentifier NOT NULL
CONSTRAINT DF_what_id DEFAULT(NEWSEQUENTIALID()),
-- or NEWID() if you like page splits
name nvarchar(128),
CONSTRAINT PK_what PRIMARY KEY (id)
);
INSERT dbo.what(name) VALUES(N'hi'),(N'there');
SELECT id, name FROM dbo.what;
Output (yours will have different values for id):
id
name
84c37c76-8c0e-ed11-ba5d-00163ef319ff
hi
85c37c76-8c0e-ed11-ba5d-00163ef319ff
there
I'm creating a user-based database for a login system. I have around 15 tables in my DB. I have a procedure that add a new user in the DB. I had created a fake user(which send internal communication) before i added the circular references in my DB, from there i created my first real user with the reference to my user 0. Then I've deleted all the accounts to repopulate it.
My table is design like this:
ID, password, ..., idSupervisor (which is the circular references)
I cannot add a new account since I don't have the first fake accounts to add a a references.
How can I add the fake account again without dropping all the database
I'm working with SQL Server 2008
EDIT: my table is created that way:
CREATE TABLE User
(
ID INT PRIMARY KEY IDENTITY,
Pass VARCHAR(100) NOT NULL,
IdSupervisor INT,
FOREIGN KEY (IdSupervisor) REFERENCES User(ID) -- Actually added after in an alter table
)
I don't want to drop the whole database. I just want to add a new fake user so i can start my user list from there.
After a lengthy comment thread on the question, it would appear that the main problem is this error message:
Cannot insert the value NULL into column 'idSupervisor', table 'DB.dbo.User'; column does not allow nulls. INSERT fails.
Given another of your comments:
It could be null
It would seem that all you need to do is allow NULL values for that column. Something like this:
ALTER TABLE [User] ALTER COLUMN [IdSupervisor] INT NULL
Simply alter the column to allow NULL values, then you can insert a record with a NULL value in that column.
I created a table for Boat that contains the following columns: BName, Type, Price, OName.
However, the Type column should be one of the following: Sailboat, Houseboat, or Deckboat.
How can I reflect this on the create table statement. I've searched about it and I came up with this statement which I'm not sure if it's right or not:
CREATE TABLE Boat
(
BName varchar(255),
BType int,
Price double,
OName varchar(255),
PRIMARY KEY (BName),
FOREIGN KEY (BType) REFERENCES BoType(ID)
);
CREATE TABLE BoType
(
ID int PRIMARY KEY,
Type varchar(255)
)
Is this the best way to do it?
You can try something like this:
mycol VARCHAR(10) NOT NULL CHECK (mycol IN('moe', 'curley', 'larry'))
Here are more details on MSSQL "Check Constraints":
http://technet.microsoft.com/en-us/library/ms188258%28v=sql.105%29.aspx
That's the best way to do it just make sure that you populate the BoType table with the desired reference values (i.e. Sailboat, Houseboat, Deckboat). Because if you use constraint then you have the user of the database who have no knowledge in SQL or have no access rights in your DB, at your mercy or they become too dependent on you. However, if you set it as a separate table then the user of your system/database even without knowledge about SQL could add or change values via your front-end program (e.g. ASP, PHP). In other words you design is more flexible and scalable not to mention less maintenance in your part.
I have two tables which are connected by m2m relationship.
CREATE TABLE words
(
id INT PRIMARY KEY,
word VARCHAR(100) UNIQUE,
counter INT
)
CREATE TABLE urls
(
id INT PRIMARY KEY,
url VARCHAR(100) UNIQUE
)
CREATE TABLE urls_words
(
url_id INT NOT NULL REFERENCES urls(id),
word_id INT NOT NULL REFERENCES words(id)
)
and i have counter field in words table. How can i automize proccess of updating counter field which is responsible for calculating how much rows stored in urls_words with particular word.
I would investigate why you want to store this value. There may be good reasons, but triggers complicate databases.
If this is a "load-then-query" database, then you can update the count when you load data -- presumably at some frequency such as once a day or once a week. You don't need to worry about triggers.
If this is a transactional database, then triggers would be needed and these add complexity to the processing. They also lock tables when you might not want them locked.
An alternative is to have an index on urls_words(word_id, url_id). This would greatly speed the calculation of the count when you need it. It also does not require triggers or locks on multiple table during an update.
Create a trigger on urls_words table which updates the counter column on words table every time a change is made (ie update, insert, delete).
More of a question concerning the database model for a specific problem. The problem is as follows:
I have a number of objects that make up the rows in a fixed table, they are all distinct (of course). One would like to create sets that contain a variable amount of these stored objects. These sets would be user-defined, therefore no hard-coding. Each set will be characterized by a number.
My question is: what advice can you experienced SQL programmers give me to implement such a feature. My most direct approach would be to create a table for each such set using table-variables or temporary tables. Finally, an already present table that contains the names of the sets (as a way to let the user know what sets are currently present in the database).
If not efficient, what direction would I be looking in to solve this?
Thanks.
Table variables and temporary tables are short lived, narrow of scope and probably not what you want to use for this. One table for each Set is also not a solution I would choose.
By the sound of it you need three tables. One for Objects, one for Sets and one for the relationship between Objects and Sets.
Something like this (using SQL Server syntax to describe the tables).
create table [Object]
(
ObjectID int identity primary key,
Name varchar(50)
-- more columns here necessary for your object.
)
go
create table [Set]
(
SetID int identity primary key,
Name varchar(50)
)
go
create table [SetObject]
(
SetID int references [Object](ObjectID),
ObjectID int references [Set](SetID),
primary key (SetID, ObjectID)
)
Here is the m:m relation as a pretty picture: