Chad, EntityFramework, Project, Datetime2, SYSDATETIME(), CreateTable
https://ask.chadgpt.ru/share/ca0f14c0-5b36-4f36-8762-0f4d76aff440
D:\VC25\gs.trade.core\GS.EvlCoreWebApi01\Ca_DB_Model_Init_03\
D:\VC25\gs.trade.core\GS.EvlCoreWebApi01\Ca_DB_Model_Init_03\Ca_DB_Model_Init_03.csproj
---------------
1. datetime2 — рекомендуемый выбор:
datetime2— более новый тип, обладает большей точностью (до 7 знаков после запятой) и может хранить более широкий диапазон дат: от 0001-01-01 до 9999-12-31.datetime— старый тип, точность до 3 миллисекунд, диапазон от 1753-01-01 до 9999-12-31.
2. Совместимость с C#:
В C# оба обычно связывают с типом DateTime.
3. Рекомендация Microsoft:
- Microsoft рекомендует использовать
datetime2для новых разработок потому что он более современный и гибкий (https://learn.microsoft.com/ru-ru/sql/t-sql/data-types/datetime2-transact-sql).
4. Пример:
В SQL:
Modified datetime2 NOT NULLВ C#:
public DateTime Modified { get; set; }или если допускается отсутствие значения:
public DateTime? Modified { get; set; }Вывод:
Выбирайте datetime2 — это лучший современный вариант.
В C# используйте DateTime (System.DateTime).
--------
Чтобы поле Modified заполнялось автоматически при добавлении записи в SQL Server, используйте тип данных datetime2 (или datetime) и укажите в определении столбца значение по умолчанию — функцию SYSDATETIME() (для datetime2) или GETDATE() (для datetime).
CREATE TABLE YourTable (
Id int PRIMARY KEY,
OtherColumn nvarchar(100),
Modified datetime2 NOT NULL DEFAULT SYSDATETIME()
);
или для уже существующей таблицы:
ALTER TABLE YourTable ADD Modified datetime2 NOT NULL DEFAULT SYSDATETIME();или, если столбец уже есть, но нет значения по умолчанию:
ALTER TABLE YourTable ADD CONSTRAINT DF_YourTable_Modified DEFAULT SYSDATETIME() FOR Modified;ПОяснения:
- DEFAULT SYSDATETIME():
- При добавлении новой записи в это поле будет автоматически поставлено текущее системное время
- (по серверу).
- Для типа datetime используйте
GETDATE(), - для datetime2 рекомендуется
SYSDATETIME() (он более точный и совместимый).
Важно:
- Это решение актуально именно для автоматического заполнения при добавлении записи, а не при обновлении.
- Для автоматического обновления Modified при обновлении записи нужна отдельная логика (например, триггер).
Абсолютно верно — если вы хотите записывать в этот столбец только дату
создания строки (а не дату последнего изменения), то логичнее назвать
его Created. Такое поле обычно один раз автоматически инициализируется
при вставке записи.- Переименовать столбец Modified в Created:
EXEC sp_rename 'YourTable.Modified', 'Created', 'COLUMN';
- Добавить/установить значение по умолчанию для Created:
Если столбца ещё нет:
ALTER TABLE YourTable
ADD Created DATETIME2 NOT NULL DEFAULT SYSDATETIME();
Если он уже есть, но без дефолта:
ALTER TABLE YourTable
ADD CONSTRAINT DF_YourTable_Created DEFAULT SYSDATETIME() FOR Created;
Теперь при каждом новом добавлении строки поле Created будет выставляться автоматически.Для проверки простой тест:
INSERT INTO YourTable (OtherField1, OtherField2)
VALUES ('value1', 'value2');
SELECT * FROM YourTable WHERE OtherField1 = 'value1';
В результате в поле Created автоматически будет стоять текущее время на момент вставки.
Modifed After String Change LATER
Trigger
Ниже приведён пример инструкции INSERT для вставки двух записей,
учитывая, что поля Created и Modified не допускают NULL, и выступают обязательными.
Если у вас нет дефолта для этих столбцов,
значения нужно явно указывать — обычно с помощью функции SYSDATETIME():
INSERT INTO [dbo].[TestTable2]
([DataInt], [DataChar], [Created], [Modified])
VALUES
(101, N'Первая запись', SYSDATETIME(), SYSDATETIME()),
(202, N'Вторая запись', SYSDATETIME(), SYSDATETIME());
Пояснения:
- Здесь для Created и Modified будет выставлено текущее время вставки (для обоих совпадёт).
- Если у вас есть требования отдельно обновлять Modified при изменении —
- обычно это делается через UPDATE или триггер.
Проверьте,
что столбцы Created/Modified создают именно sysdatetime(), если нужен
другой механизм автозаполнения — его надо прописать в таблице через
DEFAULT или триггер.
Запрос для проверки:
SELECT * FROM [dbo].[TestTable2];
В результате вы увидите обе записи с разными
(или одинаковыми, если команды были выполнены быстро) временными метками.
SELECT * FROM [dbo].[TestTable2];
В результате вы увидите обе записи с разными (или одинаковыми,
если команды были выполнены быстро) временными метками.
Конечно! Для того чтобы при вставке новых записей поля
Created и Modified автоматически заполнялись текущим временем, им нужно
задать значение по умолчанию через DEFAULT.
Это можно сделать при создании таблицы или для уже существующей с помощью ALTER TABLE.
Пример для уже существующей таблицы:
-- Для столбца Created
ALTER TABLE [dbo].[TestTable2]
ADD CONSTRAINT DF_TestTable2_Created DEFAULT (SYSDATETIME()) FOR [Created];
-- Для столбца Modified
ALTER TABLE [dbo].[TestTable2]
ADD CONSTRAINT DF_TestTable2_Modified DEFAULT (SYSDATETIME()) FOR [Modified];
Теперь, если при вставке не указывать значения для этих столбцов,
они будут автоматически заполнены текущей датой и временем.
Пример вставки — теперь без указания дат:
INSERT INTO [dbo].[TestTable2] ([DataInt], [DataChar])
VALUES (101, N'Первая запись'), (202, N'Вторая запись');
Проверьте результат:
SELECT * FROM [dbo].[TestTable2];
В столбцах Created и Modified вы увидите одинаковые значения времени на момент вставки записи.
Если
потребуется, чтобы Modified обновлялся при каждом обновлении строки,
можно создать триггер — дайте знать, если это потребуется!
В T-SQL SQL Server нет "функции" с параметрами как в обычных языках,
но можно воспользоваться динамическим SQL или, лучше, создать хранимую процедуру,
которая будет принимать параметры и создавать таблицу с нужной структурой.
Вот пример хранимой процедуры, которая принимает:
- @TableName — имя создаваемой таблицы
- @IdType — тип ID-поля:
'int' или 'bigint' (по умолчанию 'int')
Также создаёт поля ID, Created (дату создания),
Modified (дату последнего изменения, обновляется и при вставке, и при обновлении).
CREATE PROCEDURE dbo.CreateStandardTable
@TableName NVARCHAR(128),
@IdType NVARCHAR(10) = N'int'
AS
BEGIN
SET NOCOUNT ON;
-- Проверьте существование таблицы
IF EXISTS (
SELECT * FROM sys.tables WHERE name = @TableName AND schema_id = SCHEMA_ID('dbo')
)
BEGIN
RAISERROR(N'Таблица %s уже существует.', 16, 1, @TableName);
RETURN;
END
-- Собираем динамический SQL для создания таблицы
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'CREATE TABLE [dbo].[' + @TableName + N'] (
[ID] ' + @IdType + N' IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Created] DATETIME2 NOT NULL CONSTRAINT DF_' + @TableName + N'_Created DEFAULT (SYSDATETIME()),
[Modified] DATETIME2 NOT NULL CONSTRAINT DF_' + @TableName + N'_Modified DEFAULT (SYSDATETIME())
);
';
-- Выполняем создание таблицы
EXEC sp_executesql @sql;
-- Создаём триггер для автоматического обновления Modified
DECLARE @trgSql NVARCHAR(MAX);
SET @trgSql = N'
CREATE TRIGGER [TRG_' + @TableName + N'_Modified]
ON [dbo].[' + @TableName + N']
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE t
SET Modified = SYSDATETIME()
FROM [dbo].[' + @TableName + N'] t
INNER JOIN inserted i ON t.ID = i.ID;
END;
';
EXEC sp_executesql @trgSql;
END
-------------
Пояснения:
- Процедура проверяет, существует ли уже таблица с таким именем.
- Создает таблицу с указанными полями и дефолтами на даты.
- После создания добавляет триггер, который обновляет поле
Modified при UPDATE. - Поле
Created автоматически проставляется при INSERT. - Тип ID будет
int или bigint, по вашему выбору.
Как использовать:
-- стандартная таблица с int
EXEC dbo.CreateStandardTable @TableName = N'TestTable3';
-- c bigint идентификатором
EXEC dbo.CreateStandardTable @TableName = N'TestTable4', @IdType = N'bigint';
В SQL Server Management Studio (SSMS) триггеры для таблицы находятся не там же,
где хранятся процедуры.
Вот как их найти:
- Откройте Object Explorer в SSMS.
- Разверните нужную базу данных.
- Разверните папку Tables (Таблицы).
- Найдите и разверните нужную таблицу (например,
TestTable3). - Под таблицей появится папка Triggers (Триггеры) — именно там находятся все триггеры,
- связанные именно с этой таблицей.
Итого:
База данных → Tables → Ваша таблица → Triggers
В отличие от процедур
(Programmability → Stored Procedures), триггеры всегда лежат внутри
конкретной таблицы и не отображаются глобально для всей базы данных.
Как удостовериться, есть ли триггеры на таблице через запрос:
SELECT * FROM sys.triggers WHERE parent_id = OBJECT_ID('dbo.TestTable3')
или (чтобы увидеть и имя таблицы)
SELECT
t.name AS TriggerName,
p.name AS TableName
FROM
sys.triggers t
JOIN sys.tables p ON t.parent_id = p.object_id
WHERE
p.name = 'TestTable3'
Если вернуть пусто — триггеров точно нет.
Если хотите создать триггер, дайте знать, помогу с синтаксисом под ваш кейс!
Если у вас другая проблема, уточните, и я помогу разобраться.
В T-SQL (SQL Server) выполнить «пустой» INSERT без перечисления столбцов возможно
ТОЛЬКО если для всех столбцов в таблице заданы значения
по умолчанию (DEFAULT) или они являются IDENTITY/COMPUTED.
То есть, инструкция следующая:
INSERT INTO TestTable3 DEFAULT VALUES;
- Все столбцы в таблице — либо имеют значение по умолчанию (
DEFAULT constraint), - либо автоматически заполняются как
IDENTITY (автоинкремент) - или вычисляемое поле (COMPUTED COLUMN).
- Нет столбцов, обязательных для ввода (NOT NULL),
- для которых не задано значение по умолчанию.
CREATE TABLE TestTable3 (
Id INT IDENTITY(1,1) PRIMARY KEY, -- генерируется автоматически
DateCreated DATETIME DEFAULT GETDATE(),-- автоматически текущее время
RowGuid UNIQUEIDENTIFIER DEFAULT NEWID() -- автоматически новый GUID
);В такой таблице можно сделать так:
INSERT INTO TestTable3 DEFAULT VALUES;
Когда вы получите ошибку?
Если хотя бы у одного поля в таблице:
- тип NOT NULL
- и нет ни значения по умолчанию (DEFAULT), ни IDENTITY, ни вычисляемого (COMPUTED)
то INSERT DEFAULT VALUES вызовет ошибку.
Как проверить?
Сообщите структуру вашей TestTable3 (результат sp_help TestTable3 или код CREATE TABLE),
тогда я подскажу точно.
Также могу помочь написать скрипт, чтобы посмотреть, есть ли у ваших полей нужные ограничения.
Вывод:
— Если все столбцы заполняются сами (DEFAULT, IDENTITY, COMPUTED)
— можно делать пустой insert через INSERT ... DEFAULT VALUES.
— Если какая-то колонка обязательна и не имеет автоматического значения — нельзя, получите ошибку.
— Просто INSERT INTO TestTable3 VALUES (); — так делать нельзя, синтаксис не позволит
(в отличие от некоторых других СУБД, в T-SQL это не разрешено).
Если нужны примеры INSERT с полями или проверить вашу таблицу — пришлите описание.
Однако вы можете явно указать установку
столбца в его текущее значение. Например, если ваша таблица называется
TestTable3, и у неё есть столбец, допустим, Id, вы обновляете так:
UPDATE TestTable3 SET Id = Id;
Или если таблица содержит другие столбцы (например, Name), можно выполнить:
UPDATE TestTable3 SET Name = Name;
Это
обновление не меняет значения в таблице фактически, но "проходит" как
UPDATE. Все триггеры и вычисляемые поля, связанные с UPDATE (например,
поля Modified с дефолтом GETDATE() ON UPDATE или через триггер), будут
обработаны.
Если вы хотите обновить только одну строку (например, ту, которую только что вставили),
добавьте WHERE:
UPDATE TestTable3 SET Id = Id WHERE Id = 123;
— где Id = 123 — условие для нужной строки.
Важное замечание:
Поле Created
обычно заполняется один раз (при вставке), тогда как поле Modified
обновляется при каждом UPDATE (обычно через триггер или выражение типа
DEFAULT GETDATE() OVER UPDATE, если используется более современная
версия SQL Server).
Вывод:
"Пустой" UPDATE — это UPDATE с присваиванием любого столбца самого себе.
Например:
UPDATE TestTable3 SET [ЛюбойСтолбец] = [ЛюбойСтолбец];
Это защёлка для вызова триггеров,
пересчёта computed-столбцов или обновления вашего поля Modified.
UPDATE TestTable3 SET Name = Name;
оба Name
— это ссылка на одноимённый столбец таблицы. Кавычки не требуются, если
имя столбца простое, латинское и без спецсимволов или пробелов.
Однако, если бы имелся столбец с названием, например, My Name (с пробелом),
тогда его пришлось бы взять в квадратные скобки:
UPDATE TestTable3 SET [My Name] = [My Name];
Итак,
Name = Name — корректный синтаксис для стандартного столбца без кавычек/скобок. - Если столбец называется странно или совпадает с ключевым словом,
- заключите его в квадратные скобки:
[Name].
P.S. Английское слово Name
редко бывает зарезервированным в популярнейших диалектах SQL, поэтому
без скобок или кавычек писать его обычно разрешается и работает
корректно.
UPDATE TestTable3 SET Name = Name;
Оба Name обозначают не строковое значение, а имя столбца таблицы.
То есть, для каждой строки таблицы вы присваиваете столбцу Name его же текущее значение.
По сути, эта команда ничего не меняет в таблице.
Когда нужны кавычки:
Если вы хотите присвоить столбцу Name строковое значение, например,
“Петя”, тогда действительно пишется так:
UPDATE TestTable3 SET Name = 'Петя';
Здесь 'Петя' — это строковое значение, и кавычки обязательны.
Когда кавычки НЕ нужны:
В вашем изначальном варианте UPDATE TestTable3 SET Name = Name;
оба раза Name — это ссылка на столбец, никаких кавычек не надо.
Итого:
Name = Name — обе части указывают на столбец, кавычки не нужны.Name = 'something' — справа строка, кавычки нужны.
Если хотите присвоить строку, берите в кавычки.
Если копируете значения из столбца — кавычки не нужны.
Да, всё верно — ваш SQL-запрос сработал именно так, как вы ожидали.
Вот что произошло:
- Вы обновили столбец
[Name] на значение 'NAME1' только для той записи, у которой [ID] = 2. - В результате, только у записи с
[ID] = 2 поле [Name] изменилось (стало 'NAME1'), а поле [Modified]
получило новое значение времени (это обычно делается через триггер или в
ручную ставится новое время, если логика такая заложена). - У записей с
[ID] = 1 и [ID] = 3 изменений нет ([Name] остался прежним, [Modified] тоже не поменялся).
Объяснение:
Оператор UPDATE меняет только те строки, которые подходят под условие в WHERE.
Все остальные остаются без изменений.
Обновляемые столбцы (например, Modified) могут обновляться автоматически,
если в таблице есть триггер на обновление,
либо вы явно задаёте новое значение через SET Modified = GETDATE(), например.
В вашем примере видно:
- ID 1: нет обновления, поля как были, так и остались.
- ID 2: имя обновилось, время обновлено — видно, что была операция изменения строки.
- ID 3: всё без изменений.
Всё логично и подтверждает корректную работу запроса и базы данных.
Если нужно автоматически обновлять дату последних изменений (Modified),
обычно используют триггеры на таблице, или добавляют в UPDATE ещё одну колонку:
UPDATE TestTable3
SET [Name] = 'NAME1', [Modified] = GETDATE()
WHERE [ID] = 2
Тогда время изменения фиксировалось бы прямо при апдейте.
Комментариев нет:
Отправить комментарий