Ms SQL як заповнити таблицю даними. Перехід від ER-діаграми до табличної моделі

Перш ніж розпочинати створення таблиці SQL, необхідно визначити модель бази даних. Спроектувати ER-діаграму, у якій визначити сутності, атрибути та зв'язки.

Основні поняття

Сутності – предмети чи факти, інформацію про які необхідно зберігати. Наприклад, співробітник фірми чи проекти, що реалізуються підприємством. Атрибути – складова, яка описує чи кваліфікує сутність. Наприклад, атрибут сутності «працівник» – заробітна плата, а атрибут сутності «проект» – кошторисна вартість. Зв'язки – асоціації між двома елементами. Вона може бути двонаправленою. Також існує рекурсивний зв'язок, тобто зв'язок сутності із самою собою.

Також необхідно визначити ключі та умови, за яких збережеться цілісність бази даних. Що це означає? Іншими словами - обмеження, які допоможуть зберегти бази даних у правильному та узгодженому вигляді.

Перехід від ER-діаграми до табличної моделі

Правила переходу до табличної моделі:

  1. Перетворити всі сутності на таблиці.
  2. Перетворити всі атрибути на стовпці, тобто кожен атрибут сутності повинен бути відображений в імені стовпця таблиці.
  3. Унікальні ідентифікатори перетворювати на первинні ключі.
  4. Всі зв'язки перетворюються на зовнішні ключі.
  5. Здійснити створення таблиці SQL.

Створення бази

Спочатку необхідно запустити сервер MySQL. Для його запуску слід зайти в меню "Пуск", потім до "Програми", далі в MySQL і MySQL Server, вибрати MySQL-Command-Line-Client.

Для створення бази даних використовується команда Create Database. Ця функціямає наступний формат:

CREATE DATABASE назва_бази_даних.

Обмеження на назву бази такі:

  • довжина становить до 64 знаків і може включати літери, цифри, символи "" та "";
  • Ім'я може починатися з цифри, але в ньому повинні бути літери.

Потрібно пам'ятати і загальне правило: будь-який запит чи команда закінчуються роздільником (delimiter). У SQL прийнято як роздільник використовувати точку з комою.

Сервер необхідно вказати, з якою базою даних потрібно буде працювати. І тому існує оператор USE. Цей оператор має простий синтаксис: USE н азвання_бази_даних.

Створення таблиці SQL

Отже, модель спроектована, база даних створена, і сервер вказано, як саме з нею потрібно працювати. Тепер можна починати створювати таблиці SQL. Існує мова визначення даних (DDL). Він використовується для створення таблиці MS SQL, а також для визначення об'єктів та роботи з їхньою структурою. DDL включає набір команд.

SQL Server створення таблиці

Використовуючи лише одну команду DDL, можна створювати різні об'єкти бази, варіюючи її параметри. Для застосовується команда Create Table. Формат tt виглядає так:

CREATE TADLE назва_таблиці,(назва_стовпця1 назва _стовпця2тип даних [обмеження_стовпця],[обмеження_таблиці]).

Слід докладніше описати синтаксис цієї команди:

  • Назва таблиці повинна мати довжину до 30 символів та починатися з літери. Допустимо лише символи алфавіту, літери, а також символи «_», «$» та «#». Дозволено використання кирилиці. Важливо відзначити, що імена таблиць не повинні співпадати з іменами інших об'єктів і зарезервованими словами сервера бази даних, таких як Column, Table, Index і т. д.
  • Для кожного стовпчика слід обов'язково вказати тип даних. Існує стандартний набір, який використовується більшістю. Наприклад, Char, Varchar, Number, Date, тип Null тощо.

  • За допомогою параметра Default можна встановити значення за замовчуванням. Це гарантує, що у таблиці нічого очікувати невизначених значень. Як це розуміти? Значення за промовчанням може бути символ, вираз, функція. Важливо пам'ятати, що тип цих даних, заданих за замовчуванням, повинен збігатися з типом стовпця, що вводяться.
  • Обмеження на кожен стовпець використовують для забезпечення умов цілісності для даних на рівні таблиці. Є ще нюанси. Заборонено видаляти таблицю, якщо є залежні від неї інші таблиці.

Як працювати з базою

Для реалізації великих проектів найчастіше потрібно створення кількох баз даних, і кожна вимагає безліч таблиць. Звісно, ​​утримати всю інформацію в голові користувачам неможливо. Для цього передбачена можливість подивитися структуру баз даних та таблиць у них. Існує кілька команд, а саме:

  • SHOW DATABASES – показує на екрані всі створені бази даних SQL;
  • SHOW TABLES – виводить список усіх таблиць для поточної бази даних, які вибираються командою USE;
  • DESCRIBE назва_таблиці- Показує опис всіх стовпців таблиці.
  • ALTER TABLE – дозволяє змінювати структуру таблиці.

Остання команда дозволяє:

  • додати до таблиці стовпець або обмеження;
  • змінити існуючий стовпець;
  • видалити стовпець чи стовпці;
  • видалити обмеження цілісності.

Синтаксис цієї команди має такий вигляд: ALTER TABLE назва_таблиці( | | | | [(ENABLE | DISABLE) CONSTANT ім'я_обмеження ] | }.

Існують інші команди:

  • RENAME – перейменування таблиці.
  • TRUNCATE TABLE видаляє всі рядки з таблиці. Ця функція може бути потрібна, коли необхідно заповнити таблицю наново, а зберігати попередні дані немає необхідності.

Також бувають ситуації, коли структура бази змінилася і таблицю слід видалити. І тому існує команда DROP. Звичайно, попередньо потрібно вибрати базу даних, з якої потрібно видалити таблицю, якщо вона відрізняється від поточної.

Синтаксис команди є досить простим: DROP TABLE назва_таблиці.

У SQL Access створеннятаблиць та його зміна здійснюється тими самими командами, переліченими вище.

За допомогою CREATE TABLE можна створити порожню таблицю та надалі заповнити її даними. Але це ще не все. Також можна одразу створювати таблицю з іншої таблиці. Як це? Тобто існує можливість визначити таблицю та заповнити її даними іншої таблиці. Для цього існує спеціальне ключове слово AS.

Синтаксис дуже простий:

  • CREATE TABLE назва_таблиці[(визначення_стовпців)] AS підзапит;
  • визначення_стовпців -імена стовпців, правила цілісності для стовпців новоствореної таблиці та значення за замовчуванням;
  • підзапит - повертає такі рядки, які потрібно додати до нової таблиці.

Таким чином, така команда створює таблицю з певними стовпцями, вставляє до неї рядки, які повертаються у запиті.

Тимчасові таблиці

Тимчасові таблиці - це таблиці, дані у яких стираються наприкінці кожного сеансу чи раніше. Вони використовуються для запису проміжних значень чи результатів. Їх можна застосовувати як робочі таблиці. Визначати тимчасові можна будь-якому сеансі, а користуватися їх даними можна лише у поточному сеансі. Створення тимчасових таблиць SQL відбувається аналогічно звичайним з використанням команди CREATE TABLE. Щоб показати системі, що таблиця тимчасова, потрібно використовувати параметр GLOBAL TEMPORARY.

Пропозиція ON COMMIT встановлює час життя даних у такій таблиці та може виконувати наступні дії:

  • DELETE ROWS -очистити тимчасову таблицю (видалити всі дані сеансу) після кожного завершення транзакції. Зазвичай це значення використовується за замовчуванням.
  • PRESERVE ROWS - залишити дані для використання в наступній транзакції. Крім того, можна очистити таблицю лише після завершення сеансу. Але є особливості. Якщо відкат транзакції (ROLLBACK) відбувся, таблиця буде повернена до стану на кінець попередньої транзакції.

Синтаксис створення тимчасової таблиці може бути представлений таким чином: CREATE TABLE назва_таблиці,(назва_стовпця1тип даних [обмеження_стовпця], назва _стовпця2тип даних [обмеження_стовпця], [обмеження_таблиці]).

Після створення порожніх таблиць наступним логічним кроком є ​​заповнення їх даними та оновлення цих даних. Для цього Transact-SQL призначена пара інструкцій INSERT - UPDATE.

Однак часто на пізньому етапі проектування виникає необхідність змінити саму схему таблиць. Наприклад, якщо змінився первинний ключ або тип стовпця. Щоб не видаляти старі таблиці та не створювати їх заново за допомогою CREATE TABLE з правильними параметрами, застосовується інструкція ALTER TABLE. Використання цих трьох конструкцій розглядається нижче.

Заповнення таблиць

Заповнити таблицю даними можна через конструкцію CREATE TABLE, проте ефективнішим підходом є розділяти створення таблиці та її заповнення, особливо новачкам у SQL, тому що:

  • візуально зрозуміліше;
  • зручніше, якщо заповнення таблиць поетапне.

Щоб отримати наступний вид таблиці:

ВД. Мешканця

дата народження

Номер квартири

Email-адреса

Олексин. В.В.

Горбунов Д.Д.

[email protected]

Симонова К.Р

Дормітотова К.С.

[email protected]

Потрібно створити її за допомогою CREATE TABLEта заповнити, застосувавши інструкцію INSERT. Наступна інструкціядодає один рядок до вже створеної нами таблиці housemates:

Видаляємо попередня версіятаблиці DROP TABLE housemates; - Створюємо таблицю. CREATE TABLE housemates(housemeateID int NOT NULL CONSTRAINT primary_id PRIMARY KEY, housemateName nvarchar(30) NOT NULL, BithDate date NOT NULL; -- Вставляємо дані в таблицю USE GO INSERT INTO ( , , , ,) VALUES (100, "Алексин В.В.", "19721122", 11," [email protected]"), (101,"Горбунов Д.Д.","19220525",25," [email protected]"), (102,"Симонова К.Р","19560211",13," [email protected]"), (103,"Дормітотова К.С.","19770815",9," [email protected]")

У прикладі вище слід розрізняти два блоки конструкції INSERT:

INTO- що вказує на таблицю в яку додаються дані

VALUES- ініціалізуючий рядковий введення.

У параметрах (у дужках) блоку INTOперераховуються стовпці у порядку їх прямування. Допустимий запис без параметрів, якщо порядок прямування стовпців при створенні таблиці та заповненні її збігаються. Наступний код ідентичний попередньому:

INSERT INTO VALUES (100,"Алексин. В.В.","19721122",11," [email protected]"), (101,"Горбунов Д.Д.","19220525",25," [email protected]"), (102,"Симонова К.Р","19560211",13," [email protected]"), (103,"Дормітотова К.С.","19770815",9," [email protected]")

Якщо потрібно змінити порядок заповнення, це потрібно явно вказати:

INSERT INTO (,,, ,) VALUES ("Алексин. В.В.",101,"19721122"," [email protected]",11), ("Горбунов Д.Д.",102,"19220525"," [email protected]",25), ("Симонова К.Р",103,"19560211"," [email protected]",13) ("Дормітотова К.С.",104,"19770815"," [email protected]",9)

У блоці VALUES проводиться рядкова ініціалізація у порядку проходження стовпців блоку INTO. Заповнення рядка - це перерахування значень осередків у дужках. Значення перераховуються через кому, рядки між собою теж.

Застосувати конструкцію INSERT можна тільки до тих стовпців, у яких ще немає даних. Інакше виникне помилка виконання запиту.

Оновлення таблиці

Потреба оновлення таблиць виникає якщо необхідно змінити вже введені в таблицю дані. Виконується за допомогою інструкції UPDATE. Якщо INSERT працює тільки з порожніми таблицями, UPDATE тільки з заповненими. Якщо запит буде адресований незаповненим осередкам, виникне помилка.

Наступний код надасть новий Поштова скринькажителю будинку з ідентифікаційним номером 103.

UPDATE housemates SET Email = " [email protected] WHERE housemeateID = 103

Блок SET- Це блок змін. Якщо потрібно оновити значення кількох осередків, то вони перераховуються через кому.

UPDATE housemates SET Email = " [email protected]", housemateName = "Рюрік С.С." WHERE housemeateID = 103

Зміна таблиці

На пізніх етапах проектування або після розробки бази часто виникає необхідність:

  • додати або видалити стовпець;
  • змінити тип стовпця;
  • призначити стовпець чи групу стовпців первинним чи зовнішнім ключем, чи зняти ці обмеження.

Для всіх цих операцій призначено інструкцію перевизначення ATER TABLE.

Щоб додати стовпець, інструкція ALTER TABLE застосовується з пропозицією ADD. Додамо новий стовпець до таблиці housemates з минулого розділу:

ALTER TABLE housemates ADD PhoneNumber nvarchar(12) NULL;

Потрібно застосувати до нього пропозицію ALTER COLUMNвсередині ALTER TABLE:

ALTER TABLE housemates ALTER COLUMN PhoneNumber char(25) NOT NULL;

Видаляється стовпець застосуванням DROP COLUMNвсередині ALTER TABLE:

ALTER TABLE housemates DROP COLUMN PhoneNumber;

Первинний або зовнішній ключ видаляється та додається конструкціями ALTER TABLE ADD CONSTRAINT/DROP CONSTRAINT, відповідно:

Зняття обмеження первинного ключа зі стовпця housemeateID ALTER TABLE housemates DROP CONSTRAINT primary_id; - призначення стовпця housemeateID первинним ключем ALTER TABLE housemates ADD CONSTRAINT PK_ID PRIMARY KEY (housemeateID);

Якщо спробувати присвоїти таблиці первинний ключ, який вже там є транслятор запитів поверне помилку. Тому якщо в таблиці вже є первинний ключ, слід зняти його та призначити групу стовпців первинним ключем. Наприклад, так:

ALTER TABLE housemates DROP CONSTRAINT PK_ID; ALTER TABLE housemates ADD CONSTRAINT PK_ID,PK_AN PRIMARY KEY (housemeateID,apartmentnumber);

SQL - Урок 3. Створення таблиць та наповнення їх інформацією

Отже, ми познайомилися з типами даних, тепер удосконалитимемо таблиці для нашого форуму. Спочатку розберемо їх. І почнемо з таблиці users (користувачі). У ній у нас 4 стовпці:

Id_user - цілісні значення, отже буде тип int, обмежимо його 10 символами - int (10).
name – рядкове значення varchar, обмежимо його 20 символами – varchar(20).
email – рядкове значення varchar, обмежимо його 50 символами – varchar(50).
password – рядкове значення varchar, обмежимо його 15 символами – varchar(15).

Усі значення полів обов'язкові заповнення, отже треба додати тип NOT NULL.

Id_user int (10) NOT NULL
name varchar(20) NOT NULL
email varchar(50) NOT NULL

Перший стовпець, як ви пам'ятаєте з концептуальної моделі нашої БД, є первинним ключем (тобто його значення є унікальними, і вони однозначно ідентифікують запис). Слідкувати за унікальністю самостійно можна, але не раціонально. Для цього в SQL є спеціальний атрибут. AUTO_INCREMENT, який при зверненні до таблиці додавання даних вираховує максимальне значення цього стовпця, отримане значення збільшує на 1 і заносить його в стовпець. Таким чином, у цьому стовпці автоматично генерується унікальний номер, а отже, тип NOT NULL зайвий. Отже, надамо атрибут стовпцю з первинним ключем:


name varchar(20) NOT NULL
email varchar(50) NOT NULL
password varchar(15) NOT NULL

Тепер слід зазначити, що поле id_user є первинним ключем. Для цього в SQL використовується ключове слово PRIMARY KEY ()в дужках вказується ім'я ключового поля. Внесемо зміни:

Id_user int (10) AUTO_INCREMENT
name varchar(20) NOT NULL
email varchar(50) NOT NULL
password varchar(15) NOT NULL
PRIMARY KEY (id_user)

Отже, таблиця готова, і її остаточний варіант має такий вигляд:

Create table users (
id_user int (10) AUTO_INCREMENT,
name varchar(20) NOT NULL,
email varchar(50) NOT NULL,
password varchar(15) NOT NULL,
PRIMARY KEY (id_user)
);

Тепер розберемося з другою таблицею – topics (теми). Розмірковуючи аналогічно, маємо такі поля:



id_author int (10) NOT NULL
PRIMARY KEY (id_topic)

Але на моделі нашої БД поле id_author є зовнішнім ключем, тобто. воно може мати ті значення, які є в полі id_user таблиці users. Для того, щоб вказати це в SQL є ключове слово FOREIGN KEY (), яке має наступний синтаксис:

FOREIGN KEY (ім'я_стовпця_яке_є_зовнішнім_ключом) REFERENCES ім'я_таблиці_батька (ім'я_стовпця_батька);

Вкажемо, що id_author – зовнішній ключ:

Id_topic int (10) AUTO_INCREMENT
topic_name varchar(100) NOT NULL
id_author int (10) NOT NULL
PRIMARY KEY (id_topic)
FOREIGN KEY (id_author) REFERENCES users (id_user)

Таблиця готова, і її остаточний варіант виглядає так:

Create table topics (
id_topic int (10) AUTO_INCREMENT,
topic_name varchar(100) NOT NULL,

PRIMARY KEY (id_topic),
FOREIGN KEY (id_author) REFERENCES users (id_user)
);

Залишилася остання таблиця – posts (повідомлення). Тут все аналогічно, лише два зовнішніх ключа:

Create table posts (
id_post int (10) AUTO_INCREMENT,
message text NOT NULL,
id_author int (10) NOT NULL,
id_topic int (10) NOT NULL,
PRIMARY KEY (id_post),
FOREIGN KEY (id_author) REFERENCES users (id_user),
FOREIGN KEY (id_topic) REFERENCES topics (id_topic)
);

Зверніть увагу, зовнішніх ключів у таблиці може бути кілька, а первинний ключ MySQL може бути тільки один. У першому уроці ми видалили нашу БД forum, настав час створити її знову.

Запускаємо сервер MySQL (Пуск - Програми - MySQL - MySQL Server 5.1 - MySQL Command Line Client), вводимо пароль, створюємо БД forum (create database forum;), вибираємо її для використання (use forum;) та створюємо три наші таблиці:

Зверніть увагу, одну команду можна писати в кілька рядків, використовуючи клавішу Enter (MySQL автоматично підставляє символ нового рядка->), і лише після роздільника (точки з комою) натискання клавіші Enter призводить до виконання запиту.

Пам'ятайте, якщо ви зробили щось не так, можна видалити таблицю або всю БД за допомогою оператора DROP. Виправляти щось у командному рядкувкрай незручно, тому іноді (особливо на початковому етапі) простіше писати запити в якомусь редакторі, наприклад у Блокноті, а потім копіювати та вставляти їх у чорне віконце.

Отже, таблиці створені, щоб переконатися в цьому, згадаємо про команду. show tables:

І, нарешті, подивимося структуру нашої останньої таблиці:

Тепер стають зрозумілими значення всіх полів структури, крім поля DEFAULT. Це поле значень за замовчуванням. Ми могли б для якогось стовпця (або для всіх) вказати значення за замовчуванням. Наприклад, якби у нас було поле з назвою "Одружені\Заміжня" і типом ENUM ("так", "ні"), то було б розумно зробити одне зі значень значенням за замовчуванням. Синтаксис був би наступним:

Married enum ("так", "ні") NOT NULL default("так")

Тобто. це ключове слово пишеться через пробіл після вказівки типу даних, а дужках вказується значення за промовчанням.

Але повернемося до наших таблиць. Тепер нам необхідно внести дані до наших таблиць. На сайтах, ви зазвичай вводите інформацію в якісь html-форми, потім сценарій якоюсь мовою (php, java...) витягує ці дані з форми і заносить їх до БД. Робить він це за допомогою SQL-запиту на внесення даних до бази. Писати сценарії на php ми поки що не вміємо, а ось відправляти SQL-запити на внесення даних зараз навчимося.

Для цього використовується оператор INSERT. Синтаксис можна використати двох видів. Перший варіант використовується для внесення даних у всі поля таблиці:

INSERT INTO ім'я_таблиці VALUES ("значення_першого_стовпця","значення_другого_стовпця", ..., "значення_останнього_стовпця");


Спробуймо внести в нашу таблицю users наступні значення:

INSERT INTO users VALUES ("1","sergey", " [email protected]", "1111");

Другий варіант використовується для внесення даних у деякі поля таблиці:

INSERT INTO ім'я_таблиці ("ім'я_стовпця", "ім'я_стовпця") VALUES ("значення_першого_стовпця","значення_другого_стовпця");


У нашій таблиці users всі поля є обов'язковими для заповнення, але наше перше поле має ключове слово - AUTO_INCREMENT (тобто воно заповнюється автоматично), тому ми можемо пропустити цей стовпець:

INSERT INTO users (name, email, password) VALUES ("valera", " [email protected]", "2222");

Якби ми були поля з типом NULL, тобто. необов'язкові для заповнення, ми теж могли їх проігнорувати. Якщо спробувати залишити порожнім поле зі значенням NOT NULL, то сервер видасть повідомлення про помилку і не виконає запит. Крім того, під час внесення даних сервер перевіряє зв'язки між таблицями. Тому вам не вдасться внести в поле, що є зовнішнім ключем, значення, яке немає у зв'язаної таблиці. У цьому ви переконаєтеся, вносячи дані в дві таблиці, що залишилися.

Але насамперед внесемо інформацію ще про кількох користувачів. Щоб додати відразу кілька рядків, треба просто перераховувати дужки зі значеннями через кому:

Тепер внесемо дані до другої таблиці - topics (теми). Все теж саме, але треба пам'ятати, що значення в полі id_author повинні бути присутніми в таблиці users (користувачі):

Тепер давайте спробуємо внести ще одну тему, але з id_author, якого в таблиці users немає (оскільки ми внесли в таблицю users тільки 5 користувачів, то id=6 не існує):

Сервер видає помилку і каже, що може внести такий рядок, т.к. у полі, що є зовнішнім ключем, стоїть значення, яке немає у зв'язаної таблиці users.

Тепер внесемо кілька рядків у таблицю posts (повідомлення), пам'ятаючи, що у ній ми 2 зовнішніх ключа, тобто. id_author та id_topic, які ми будемо вносити повинні бути присутніми у пов'язаних з ними таблицях:

Отже, ми маємо 3 таблиці, в яких є дані. Постає питання – як подивитися, які дані зберігаються в таблицях. Цим ми займемося на наступному уроці.

  • Як об'єднати інструкції SELECT, щоб я міг розрахувати відсотки, успіхи та невдачі в SQL Server?
  • SQL: як вибрати окремі рядки на основі деяких значень властивостей
  • Як вибрати продукт із максимальною ціною кожної категорії?
LevelId Min Product 1 x 1 2 y 1 3 z 1 4 a 1

Мені потрібно дублювати ті самі дані в базі даних, змінивши лише ідентифікатор продукту від 1 2,3. 40

LevelId Min Product 1 x 2 2 y 2 3 z 2 4 a 2

Я міг би зробити щось на зразок

INSERT INTO dbo.Levels SELECT top 4 * fROM dbo.Levels але це просто скопіює дані. Чи є спосіб, яким я можу скопіювати дані та вставити його, змінюючи лише значення Product?

Ви найбільше на шляху – вам потрібно зробити ще один логічний крок:

INSERT INTO dbo.Levels (LevelID, Min, Product) SELECT LevelID, Min, 2 FROM dbo.Levels WHERE Product = 1

… дублюватиме рядки з іншим ідентифікатором продукту.

Також врахуйте, що WHERE Product = 1 буде надійнішим, ніж TOP 4 . Як тільки у вас буде більше чотирьох рядків у таблиці, ви не зможете гарантувати, що TOP 4 поверне ті ж чотири рядки, якщо ви також не додасте ORDER BY для вибору, однак WHERE Product = ... завжди повертатиме той же і буде продовжувати працювати, навіть якщо ви додасте додатковий рядок з ідентифікатором продукту 1 (де вам потрібно буде розглянути можливість зміни TOP 4 до TOP 5 тощо, якщо додати додаткові рядки).

Ви можете створити ідентифікатор продукту, а потім завантажити його в:

< 40) INSERT INTO dbo.Levels(`min`, product) SELECT `min`, cte.n as product fROM dbo.Levels l cross join cte where l.productId = 1;

Це передбачає, що LevelId є стовпцем ідентифікатора, який автоматично збільшується під час вставки. Якщо не:

With cte as (select 2 as n union all select n + 1 from cte where n< 40) INSERT INTO dbo.Levels(levelid, `min`, product) SELECT l.levelid+(cte.n-1)*4, `min`, cte.n as product fROM dbo.Levels l cross join cte where l.productId = 1;

INSERT INTO dbo.Levels (LevelId, Min, Product) SELECT TOP 4 LevelId, Min, 2 FROM dbo.Levels

Ви можете включати вирази в SELECT або жорстко задані значення, або щось на зразок Product + 1 або щось ще.

Я чекаю, що ви, мабуть, не захочете вставляти LevelId, але залиште це там, щоб відповідати вашому зразку. Якщо ви не хочете, щоб це видалялося з розділів INSERT і SELECT .

Наприклад, можна використовувати CROSS JOIN для таблиці чисел.

WITH L0 AS(SELECT 1 AS C UNION ALL SELECT 1 AS O), -- 2 рядки L1 AS(SELECT 1 AS C FROM L0 AS A CROSS JOIN L0 AS B), -- 4 rows Nums AS(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS N FROM L1) SELECT lvl., lvl., num.[N] FROM dbo. lvl CROSS JOIN Nums num

Це повторюватиметься 4 рази.