Sql внешний ключ - PullRequest
       9

Sql внешний ключ

0 голосов
/ 02 ноября 2011

Я пытаюсь сохранить 40 текстовых документов в базе данных. Сначала я создал таблицу, в которой хранятся идентификаторы и имена файлов. Во-вторых, я создал таблицу (WORDS), в которой будет храниться содержимое всех 40 текстовых файлов (слово в слово). Мне нужно создать внешний ключ в таблице (WORDS), чтобы ссылаться на каждое слово в его исходном файле, где оно найдено.

Очевидно, что это будет трудно, если я сделаю это вручную, так как, возможно, там миллион слов.

Мой первый вопрос: есть ли способ, которым я могу сделать этот подход автоматически? используя sql запрос?

Мой второй вопрос: как сервер SQL распознает, какое слово в каком файле находится изначально?

1 Ответ

0 голосов
/ 04 ноября 2011

Sql Server (и многие другие базы данных) изначально поддерживают полнотекстовый поиск, что в целом будет гораздо лучшим решением, чем вы предлагаете.

См. http://msdn.microsoft.com/en-us/library/ms142571.aspx

Тем не менее, если вам действительно нужен ваш подход, вы можете сделать что-то вроде следующего:

CREATE table fileTable 
(
    ID int identity,
    nameOfFile nvarchar(200),
    PRIMARY KEY (ID),
    UNIQUE(nameOfFile)
)
GO

CREATE table words
(
    ID int identity,
    word nvarchar(200),
    PRIMARY KEY(ID),
    UNIQUE(word)
)
GO

CREATE table file_words
(
    fileId int,
    wordId int,
    FOREIGN KEY (fileId) REFERENCES fileTable(ID),
    FOREIGN KEY (wordId) REFERENCES words(ID),
    UNIQUE(fileId,wordId)
)
GO

declare @fileContents nvarchar(max)
SET @fileContents = 'Hello world.  I am a silly word splitter.'
declare @fileName nvarchar(200)
SET @fileName = 'HelloSplitter.txt'


declare @whiteSpaceOrPunctuation table
(
    charVal nchar(1)
)

insert @whiteSpaceOrPunctuation
SELECT ' ' UNION ALL SELECT ',' UNION ALL SELECT ';' UNION ALL SELECT ':'
UNION ALL SELECT '-' UNION ALL SELECT '_'  UNION ALL SELECT '['  UNION ALL SELECT ']' 
UNION ALL SELECT '!' UNION ALL SELECT '.' UNION ALL SELECT '?' UNION ALL SELECT '%' 
UNION ALL SELECT '$' UNION ALL SELECT '#'
--etc...

declare @position int
declare @word nvarchar(max)
declare @fileLength int
declare @fileId int
declare @wordId int
SET @position = 1
SET @fileLength = LEN(@fileContents)
SET @word = ''
declare @currentChar nchar

INSERT fileTable (nameOfFile) VALUES (@fileName)

SELECT @fileId = SCOPE_IDENTITY()



while (@position <= @fileLength + 1)
BEGIN
    --print @position
    --print @fileLength

    SELECT @currentChar = SUBSTRING(@fileContents, @position, 1)

    --print @currentChar

    IF (EXISTS(SELECT 1 FROM @whiteSpaceOrPunctuation WHERE charVal = @currentChar) OR @position = @fileLength + 1)
    BEGIN
        --print 'word: ' + @word
        IF(@word <> '')
        BEGIN
            --print @word

            SELECT @wordId = ID FROM words where word=@word

            IF (@wordId IS NULL)
            BEGIN
                INSERT words (word) VALUES (@word)
                SELECT @wordId = SCOPE_IDENTITY()
            END

            IF (NOT EXISTS(SELECT 1 FROM file_words WHERE wordId = @wordId AND fileId=@fileId))
            BEGIN
                INSERT file_words (fileId, wordId) VALUES (@fileId, @wordId)
            END
            SET @word = ''
            SET @wordId = null
        END
    END
    ELSE BEGIN
        SELECT @word = @word + @currentChar
    END

    SELECT @position = @position + 1
END

--select * from fileTable
--select * from words
--select * from file_words

--drop table file_words
--drop table words
--drop table fileTable

Обратите внимание, что это не учитывает верхний и нижний регистр.Поведение, которое вы получите, вероятно, будет зависеть от вашего сопоставления .

Кроме того, было бы целесообразно обернуть все это в транзакцию, которую вы можете сделать либо непосредственно в этом сценарии, либо в любом другомпрограммирование API, которое вы используете для вызова db.

...