2015-08-25 2 views
2

Привет Я пытаюсь создать несколько таблиц из главной таблицы на SQL-сервере. напримерРазделите основную таблицу на несколько таблиц с помощью SQL-сервера

Основная таблица выглядит

A 1 
A 2 
A 3 
B 4 
B 5 
B 6 

Вывод должен выглядеть следующим образом:

таблице А:

A 1 
A 2 
A 3 

Таблица B:

B 4 
B 5 
B 6 

Т его главная таблица обновляется каждую неделю, поэтому могут иметь разные алфавиты. Поэтому я хочу создать динамический запрос, который автоматически разделит основную таблицу на «n» разных таблиц в зависимости от количества разных n, а также назовите таблицу на основе n-го значения.

+0

Действительно, создание новых таблиц динамически на основе другой таблицы ??? Это хороший дизайн? – lad2025

+0

Зачем вам это нужно? Вам лучше со всеми строками в одной таблице. –

+0

Мне нужно отправить копию маленькой таблицы соответствующим пользователям. – anuragsodhi

ответ

2

Да это достижимо, но Curse and Blessing Dynamic SQL by Erland Sommarskog

CREATE TABLE @tbl

Желание здесь, чтобы создать таблицу из которой имя определяется во время выполнения.

Если мы просто рассмотрим аргументы против использования динамического SQL в хранимых процедурах, некоторые из них действительно применимы здесь. Если хранимая процедура имеет в ней статическую CREATE TABLE, пользователь, выполняющий эту процедуру, должен иметь разрешения для создания таблиц, поэтому динамический SQL ничего не изменит. Планирование кэширования, очевидно, не имеет к этому никакого отношения. И т.д.

Тем не менее: Почему? Зачем вам это делать? Если вы создаете таблицы на лету в своем приложении, вы пропустили некоторые основы проектирования базы данных. В реляционной базе данных предполагается, что набор таблиц и столбцов будет постоянным. Они могут меняться с установкой новых версий, но не во время выполнения.

Иногда, когда люди делают это, кажется, что они хотят создавать уникальные имена для временных таблиц. Это совершенно не нужно, поскольку это встроенная функция SQL Server. Если вы говорите:

CREATE TABLE #nisse (а Int NOT NULL)

то фактическое имя негласно будет что-то гораздо больше, и никакие другие соединения не смогут увидеть этот экземпляр # Nisse.

Если вы хотите создать постоянную таблицу, которая уникальна для пользователя, но вы не хотите оставаться на связи и, следовательно, не можете использовать временные таблицы, возможно, лучше создать одну таблицу, которую могут использовать все клиенты, но где первый столбец является ключом, который является частным для клиента. Я обсуждаю этот метод немного ближе в своей статье «Как делиться данными между хранимыми процедурами».

Возможное решение с использованием Инлайн параметризованном Table-значной функции (вы можете использовать хранимые процедуры, если это необходимо):

CREATE FUNCTION dbo.fxnExample (@Parameter1 NVARCHAR(1)) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT id, value 
    FROM TableName 
    WHERE id = @Parameter1 
) 

-- Usage Example 
SELECT * FROM dbo.fxnExample('A') -- only data from 'A' 
SELECT * FROM dbo.fxnExample('B') -- only data from 'B' 

EDIT

Вы можете использовать представление для этого и передать их пользователям , Если вы все еще хотите, чтобы таблицы могли менять код, вы должны получить эту идею. Почему мнения, потому что таблица по-прежнему одна, и вы получаете динамический VIEW, который может имитировать ваши несколько таблиц. Также, когда данные будут обновлены в главной таблице, все ваши представления сразу получат ее, нет необходимости обновлять/вставлять.

SqlFiddleDemo

DBFiddle Demo (updated)

CREATE TABLE main_tab(suffix NVARCHAR(10) NOT NULL, val INT); 

INSERT INTO main_tab(suffix, val) 
VALUES ('A', 1), ('A', 2), ('A', 3), 
     ('B', 4), ('B', 5), ('B', 6), 
     ('C', 7), ('C', 8), ('C', 9); 


/* Get list of suffixes */ 
SELECT suffix, 
     [row_id] = ROW_NUMBER() OVER(ORDER BY suffix) 
INTO #temp 
FROM main_tab 
GROUP BY suffix; 

DECLARE @name_suffix NVARCHAR(100), 
     @sql NVARCHAR(MAX), 
     @view_name NVARCHAR(MAX), 
     @index INT = 1, 
     @total INT = (SELECT COUNT(*) FROM #temp); 

/* I used simple while loop but you can change to CURSOR if needed */ 
WHILE (@index <= @total) 
BEGIN 

    SELECT @name_suffix = suffix 
    FROM #temp 
    WHERE row_id = @index; 

    SELECT @sql = 
      N'CREATE VIEW [dbo].[[email protected]_suffix] 
      AS 
      SELECT 
      t.suffix, 
      t.val 
      FROM [dbo].[main_tab] t 
      WHERE t.suffix = ''@name_suffix'' 
      WITH CHECK OPTION' 

    SELECT 
     @view_name = REPLACE('[dbo].[[email protected]]', '@name', @name_suffix) 
     ,@sql = REPLACE(@sql, '@name_suffix', @name_suffix) 

    /* Check if view exists, if not create one */ 
    /* Instead of EXEC you can use EXEC [dbo].[sp_executesql] 
     and pass params explicitly */ 
    IF OBJECT_ID(@view_name, 'V') IS NULL    
     EXEC(@sql) 

    SET @index += 1; 
END    

/* Check if you can query views */ 
SELECT * 
FROM ViewA; 

SELECT * 
FROM ViewB; 

SELECT * 
FROM ViewC; 
+0

. Я рассмотрю, как делиться данными между хранимыми процедурами и отчитываться. Причина, по которой я хочу создать таблицу «на лету». (не на самом деле «на лету» я их теряю в базе данных, но в конечном итоге я хочу запустить сценарий, который обновит все небольшие таблицы, когда данные будут обновлены в основных таблицах (и может привести к добавлению еще нескольких таблиц в зависимости от этот уникальный столбец) – anuragsodhi

+1

@ user3765371 Обновите свой ответ. – lad2025

+0

большое спасибо, но я хочу автоматически передавать A, B и не указывать A и B в SELECT * FROM dbo.fxnExample ('A'), потому что есть еще много A и B, и они меняются каждую неделю – anuragsodhi