SQL Server 2012 - Create Data Type from existing table - sql

I have a stored procedure which accepts a user-defined table type called dbo.NodeTableType:
ALTER PROCEDURE [dbo].[InsertNonExistingNode]
(#TableVariable dbo.NodeTableType READONLY)
It seems redundant, because the dbo.NodeTableType is identical to an actual table in my database dbo.Nodes.
Do I really have to create this data-type in order to except it as a parameter in my stored procedure?
If the answer to #1 is "Yes", then is there a way to create this data-type by pointing it at the table? Currently, I have to create it this way:
CREATE TYPE NodeTableType AS TABLE
(NodeTypeId SMALLINT NOT NULL,
Location NVARCHAR(50) NULL,
DisplayName NVARCHAR(100) NULL,
AccessLevel SMALLINT NOT NULL,
IsEnabled BIT NOT NULL,
CreatedOn DATETIME2(7) NULL,
CreatedBy NVARCHAR(150) NULL,
ModifiedOn DATETIME2(7) NULL,
ModifiedBy NVARCHAR(150) NULL,
NativeId BIGINT NOT NULL,
SourceId INT NOT NULL,
Name NVARCHAR(100) NOT NULL,
Alias NVARCHAR(100) NULL
)

The only way to define a user-defined table type is through CREATE TYPE statement according to documentation at this URL: User Defined Types. So you cannot use a table for this.
I would recommend to stick to the standard practice of passing a table valued parameter that has been created with CREATE TYPE.
Another approach as outlined below can be used provided you can live without passing a table valued parameter to your procedure, and I am not sure if that is possible in your case.
In your stored procedure, you could populate a table variable of the same type as the original NodeTableType type. Of course, you would need to decide the logic for populating this table variable; I have assumed that the logic is something as simple as NodeId < 10 as an example only; in your case this rule would be different and probably more complex.
DECLARE #myTable dbo.NodeTableType;
INSERT INTO #myTable(
NodeTypeId SMALLINT NOT NULL,
Location NVARCHAR(50) NULL,
DisplayName NVARCHAR(100) NULL,
AccessLevel SMALLINT NOT NULL,
IsEnabled BIT NOT NULL,
CreatedOn DATETIME2(7) NULL,
CreatedBy NVARCHAR(150) NULL,
ModifiedOn DATETIME2(7) NULL,
ModifiedBy NVARCHAR(150) NULL,
NativeId BIGINT NOT NULL,
SourceId INT NOT NULL,
Name NVARCHAR(100) NOT NULL,
Alias NVARCHAR(100) NULL)
SELECT * from dbo.Nodes where NodeId < 10;
--now you can use #myTable rather than #TableVariable
--in your stored procedure

Related

Postgresql generated column fails when concating not null columns

I have this table definition in pgAdmin4:
CREATE TABLE IF NOT EXISTS cdr_event
(
id bigint primary key generated always as identity,
start_time timestamptz NOT NULL DEFAULT now(),
end_time timestamptz NULL,
group_id VARCHAR(10) NOT NULL,
environment VARCHAR(10) NOT NULL,
level VARCHAR(10) NOT NULL,
schema VARCHAR(30) NOT NULL,
instance INTEGER NOT NULL,
hive_instance_db_name VARCHAR(100) GENERATED ALWAYS AS (group_id||'_'||environment||'_'||level||'_'||schema||'_'||instance) STORED,
hive_static_db_name VARCHAR(100) GENERATED ALWAYS AS (group_id||'_'||environment||'_'||level||'_'||schema) STORED,
);
this fails with
ERROR: generation expression is not immutable
SQL state: 42P17
Why does postgres consider the concat mutable when the dependent columns are all NOT NULL? This thread suggests it should work
Is there anyway to create a concat-ed generated column without creating a custom concat function?
Thanks
Try keeping the involved columns of the same type, e.g. casting instance to text should do the trick:
CREATE TABLE IF NOT EXISTS cdr_event
(
id bigint primary key generated always as identity,
start_time timestamptz NOT NULL DEFAULT now(),
end_time timestamptz NULL,
group_id VARCHAR(10) NOT NULL,
environment VARCHAR(10) NOT NULL,
level VARCHAR(10) NOT NULL,
schema VARCHAR(30) NOT NULL,
instance INTEGER NOT NULL,
hive_instance_db_name VARCHAR(100) GENERATED ALWAYS AS (group_id||'_'||environment||'_'||level||'_'||schema||'_'||instance::text) STORED,
hive_static_db_name VARCHAR(100) GENERATED ALWAYS AS (group_id||'_'||environment||'_'||level||'_'||schema) STORED
);
Consider using text instead of varchar.
Demo: db<>fiddle

SQL Trigger on Insert to call a Function and Manipulate Values

I am having a problem knowing set up a trigger on insert to call a function and passing an identifier SiteID to that function which then operates on variables from another table.
I have the table, where values are inserted:
CREATE TABLE [dbo].[Tests] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
Every time a value is inserted in to the Tests table I would like a function to be called which uses the table Review to perform a simple calculation (see the trigger down the post below):
CREATE TABLE [dbo].[Review] (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
[Performed] INT NULL,
[Remaining] INT NULL
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
This is my sqlfiddle so far, however, I am unable to save it with the functions I am working on, which are here:
The trigger - not sure how to pass the SiteID for the insert or call the function:
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
CALL CalcRemaining() //how to pass it SiteID?
and the the function itself:
CREATE FUNCTION [dbo].[CalcRemaining](#ID NVARCHAR (128))
RETURNS NULL
AS
BEGIN
SELECT (Supplied, Performed FROM Review WHERE SiteID = ID);
Performed = Performed + 1;
INSERT INTO Review (Performed, Remaining) VALUES (Performed, (Supplied-Performed))
RETURN;
END
The idea is that the SiteID from the inserted line is passed to the function when called, the function then selects the values Supplied and Performed for that matching SiteID from the Review table. The Performed value is incremented by 1 and that new value along with the retrieved Supplied value are subtracted and written to the Remaining field in the Review table.
If the assumptions I've asked about in the comments are valid (that Remaining and Performed can always be calculated), here's how I'd implement your database structure, with no trigger nor function:
Base tables:
CREATE TABLE dbo.Tests (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE dbo._Review (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
Then a view that calculates Performed:
CREATE VIEW dbo._Tests_Count
WITH SCHEMABINDING
AS
SELECT
SiteID,
COUNT_BIG(*) as Performed
FROM
dbo.Tests t
GROUP BY SiteID
GO
CREATE UNIQUE CLUSTERED INDEX IX_Tests_Count ON dbo._Tests_Count (SiteID)
And finally a view that re-creates the original Review table:
CREATE VIEW dbo.Review
WITH SCHEMABINDING
AS
SELECT
r.SiteID,
r.TubNum,
r.Supplied,
COALESCE(tc.Performed,0) as Performed,
r.Supplied - COALESCE(tc.Performed,0) as Remaining
FROM
dbo._Review r
left join
dbo._Tests_Count tc WITH (NOEXPAND)
on
r.SiteID = tc.SiteID
GO
If needed, at this point a trigger could be created on this Review view to allow any INSERTs, DELETEs and UPDATEs to be performed against it rather than _Review, if you cannot change some calling code.
You have to be completely sure you're manipulating ONLY one row at a time!
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
DECLARE #SiteID NVARCHAR (128)
SELECT #SiteID = ID FROM inserted
CALL CalcRemaining(#SiteID)

Create Table - Time Statement

I am having trouble trying to create a table using MS Access.
I know for sure my problem lies in the "datetime" field but I can not figure what I am missing or doing wrong.
When I click "run" I get the
"Syntax Error in Field Definition"
Create Table Appointments
(DocID char(4) not null primary key,
PatID char(8) not null,
Day varchar(8) not null,
Time datetime not null,
Procedure varchar(50) null);
Time and procedure are reserved words, and therefore should be escaped:
Create Table Appointments
(DocID char(4) not null primary key,
PatID char(8) not null,
[Day] varchar(8) not null,
[Time] datetime not null,
[Procedure] varchar(50) null);
Or better yet, find names that aren't reserved words:
Create Table Appointments
(DocID char(4) not null primary key,
PatID char(8) not null,
AppointmentDay varchar(8) not null,
AppointmentTime datetime not null,
MedicalProcedure varchar(50) null);
Here Procedure and Time are reserved words and so need to be escaped using [] like below. See Documentation for more information
Create Table Appointments
(DocID char(4) not null primary key,
PatID char(8) not null,
[Day] varchar(8) not null,
[Time] datetime not null,
[Procedure] varchar(50) null);
As Time & Procedure are reserved keyword, so wrap Time & Procedure column in brackets [] or choose alternate names, if possible. See List of Keyword
[Time] and [Procedure]

an error occured while the batch was being executed

I'm trying to make a simple table in a database.
CREATE TABLE [dbo].[klanten]
(
[Klant_naam] TEXT NOT NULL PRIMARY KEY,
[Klant_adres] TEXT NULL,
[klant_gsm] TEXT NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] TEXT NOT NULL
)
When I try to update it, the following error pops-up.
As the documentation warns:
ntext , text, and image data types will be removed in a future version
of Microsoft SQL Server. Avoid using these data types in new
development work, and plan to modify applications that currently use
them. Use nvarchar(max), varchar(max), and varbinary(max) instead.
So, try this instead:
CREATE TABLE [dbo].[klanten] (
[Klant_naam] varchar(max) NOT NULL PRIMARY KEY,
[Klant_adres] varchar(max) NULL,
[klant_gsm] varchar(max) NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] varchar(max) NOT NULL
)
Well, this doesn't quite work either, because there is a limit of 900 bytes for index keys. How about using a surrogate key and reasonable column lengths?
CREATE TABLE [dbo].[klanten] (
Klant_Id int not null identity(1, 1) primary key,
[Klant_naam] varchar(255) NOT NULL unique,
[Klant_adres] varchar(max) NULL,
[klant_gsm] varchar(max) NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] varchar(max) NOT NULL
);
Try to change "TEXT" data type to "NCHAR()" or any other similar to this.
This error usually occured when you try to update database, but some fields can't be updated. For example, I have 5 fields in a table:
[Id] INT IDENTITY (1, 1) NOT NULL,
[Path] NVARCHAR (MAX) NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Url] NVARCHAR (MAX) NULL,
[SecureUrl] NVARCHAR (MAX) NULL
I've worked for some time with it, and make some records. And some of them have value NULL at [Url]. Suddenly I decide to change table:
[Id] INT IDENTITY (1, 1) NOT NULL,
[Path] NVARCHAR (MAX) NOT NULL,
[Name] NVARCHAR (50) NULL,
[Url] NVARCHAR (MAX) NOT NULL, //!!! HERE A PROBLEM, I ALREADY HAVE NULL RECORDS IN DATA
[SecureUrl] NVARCHAR (MAX) NULL
Problem is that my data has been made with the old model and it has records with the NULL at [Url], but in new model NULL value can't be at [Url]. So as with new model, old data can't be correct. Thus we have the error when update.

How to Sql defined function as columns e.g User_Id int when creating tables [duplicate]

I am creating tables in Sql Management Studio 2012 using SQL. How do I make fields or columns with names that are already defined in Sql Server e.g User_ID, User_Name. I want to use them as fields in my tables.
Table definition from Duplicate Post:
create table Ticket(
Ticket_Id varchar(10) not null,
TicketType_Id varchar(3) not null,
Ticket_PurchaseDate DateTime null,
LottoDraw_Id int null,
User_Id int null,
Ticket_IsWinner bit null
Primary Key(Ticket_Id,TicketType_Id)
)
Warp the column name like in brackets [ ] ... such as
create table Ticket(
Ticket_Id varchar(10) not null,
TicketType_Id varchar(3) not null,
Ticket_PurchaseDate DateTime null,
LottoDraw_Id int null,
[User_Id] int null,
Ticket_IsWinner bit null
Primary Key(Ticket_Id,TicketType_Id)
)