在 SQL/Vb.net 中的多个表之间填充主键/外键
Posted
技术标签:
【中文标题】在 SQL/Vb.net 中的多个表之间填充主键/外键【英文标题】:Populating Primary/foreign keys between multiple tables in SQL/Vb.net 【发布时间】:2019-01-29 10:09:15 【问题描述】:我正在创建一个程序,用户可以在其中上传歌曲,并且这些歌曲的元数据(例如其专辑或艺术家)记录在关系 sql 数据库中。我当前的表设置包含 3 个表 - Song_DB、Album_DB、Artist_DB。
SONG_DB:
CREATE TABLE [dbo].[SONGS_DB] (
[SONG_ID] INT IDENTITY (1, 1) NOT NULL,
[SONG_NAME] NCHAR (100) NOT NULL,
[ARTIST_ID] INT NULL,
[ALBUM_ID] INT NULL,
[SONG_LENGTH] TIME (0) NOT NULL,
[SONG_PLAYLIST_ID] INT NULL,
PRIMARY KEY CLUSTERED ([SONG_ID] ASC),
CONSTRAINT [FK_SONGS_DB_ToARTIST] FOREIGN KEY ([ARTIST_ID]) REFERENCES [dbo].[ARTIST_DB] ([ARTIST_ID]),
CONSTRAINT [FK_SONGS_DB_ToALBUM] FOREIGN KEY ([ALBUM_ID]) REFERENCES [dbo].[ALBUM_DB] ([ALBUM_ID]),
CONSTRAINT [FK_SONGS_DB_ToSONG_PLAYLIST] FOREIGN KEY ([SONG_PLAYLIST_ID]) REFERENCES [dbo].[SONG_PLAYLIST] ([SONG_PLAYLIST_ID])
Artist_DB
CREATE TABLE [dbo].[ARTIST_DB] (
[ARTIST_ID] INT IDENTITY (1, 1) NOT NULL,
[SONG_ID] INT NULL,
[NAME] TEXT NULL,
PRIMARY KEY CLUSTERED ([ARTIST_ID] ASC),
CONSTRAINT [FK_ARTIST_DB_ToSONGS_DB] FOREIGN KEY ([SONG_ID]) REFERENCES [dbo].[SONGS_DB] ([SONG_ID])
);
专辑数据库
CREATE TABLE [dbo].[ALBUM_DB] (
[ALBUM_ID] INT IDENTITY (1, 1) NOT NULL,
[SONG_ID] INT NULL,
[NAME] NCHAR (100) NULL,
PRIMARY KEY CLUSTERED ([ALBUM_ID] ASC),
CONSTRAINT [FK_ALBUM_DB_SONGS] FOREIGN KEY ([SONG_ID]) REFERENCES [dbo].[SONGS_DB] ([SONG_ID])
);
一旦上传歌曲并将元数据收集到变量中,我会尝试写入表格。我已经写下了实际的写作,但我正在努力弄清楚如何填充外键表。例如,使用以下代码,在 Artist/album_DB 中既不会填充 song_ID,在 Song_DB 中也不会填充 Album/artist_ID-
Dim SQLcon As New SqlConnection With .ConnectionString = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\coolj\OneDrive\Documents\Loop\Loop\Songs_SQL.mdf;Integrated Security=True"
Dim SQLCmd As SqlCommand
Dim SQLCmd2 As SqlCommand
Dim SQLCmd3 As SqlCommand
Dim SQLCmd4 As SqlCommand
Dim SQLCmd5 As SqlCommand
Dim SQLCmd_SID As SqlCommand
Dim SQLCmd_ARID As SqlCommand
Dim SQLCmd_ALID As SqlCommand
Dim SQLCmd_ARID2 As SqlCommand
Dim SQLCmd_ALID2 As SqlCommand
Dim SID
Dim ARID
Dim ALID
SQLcon.Open()
SQLCmd = New SqlCommand("INSERT INTO SONGS_DB (SONG_NAME, SONG_LENGTH) VALUES (@SONG_NAME, @SONG_LENGTH)", SQLcon)
SQLCmd.Parameters.AddWithValue("@SONG_NAME", Title)
SQLCmd.Parameters.AddWithValue("@SONG_LENGTH", Duration)
SQLCmd_SID = New SqlCommand("SELECT max(SONG_ID) FROM SONGS_DB", SQLcon)
If SID = "" Then
SID += 1
Else
SID = SQLCmd_SID.ExecuteScalar()
SID = Convert.ToInt32(SID)
End If
If Album IsNot "" Then
SQLCmd2 = New SqlCommand("INSERT INTO ALBUM_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd2.Parameters.AddWithValue("@NAME", Album)
'SQLCmd2.Parameters.AddWithValue("@SONG_ID", SID)
End If
If Artist IsNot "" Then
SQLCmd3 = New SqlCommand("INSERT INTO ARTIST_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd3.Parameters.AddWithValue("@NAME", Artist)
'SQLCmd3.Parameters.AddWithValue("@SONG_ID", SID)
End If
SQLCmd.ExecuteNonQuery()
If Album IsNot "" Then
SQLCmd2.ExecuteNonQuery()
End If
If Artist IsNot "" Then
SQLCmd3.ExecuteNonQuery()
End If
If Artist IsNot "" Then
SQLCmd_ARID = New SqlCommand("SELECT max(ARTIST_ID) FROM ARTIST_DB", SQLcon)
If ARID = "" Then
ARID += 1
Else
ARID = SQLCmd_ARID.ExecuteScalar()
ARID = Convert.ToInt32(ARID)
End If
SQLCmd_ARID2 = New SqlCommand("UPDATE SONG_DB SET ARTIST_ID = (@ARTIST_ID) WHERE SONG_ID = (@SONG_ID)", SQLcon)
SQLCmd_ARID2.Parameters.AddWithValue("@ARTIST_ID", ARID)
SQLCmd_ARID2.Parameters.AddWithValue("@SONG_ID", SID)
End If
If Album IsNot "" Then
SQLCmd_ALID = New SqlCommand("SELECT max(ALBUM_ID) FROM ALBUM_DB", SQLcon)
If ALID = "" Then
ALID += 1
Else
ALID = SQLCmd_ARID.ExecuteScalar()
ALID = Convert.ToInt32(ARID)
End If
SQLCmd_ALID2 = New SqlCommand("UPDATE SONG_DB SET ARTIST_ID = (@ARTIST_ID) WHERE SONG_ID = (@SONG_ID)", SQLcon)
SQLCmd_ALID2.Parameters.AddWithValue("@ARTIST_ID", ARID)
SQLCmd_ALID2.Parameters.AddWithValue("@SONG_ID", SID)
End If
If Artist IsNot "" Then
SQLCmd_ARID2.ExecuteNonQuery()
End If
If Album IsNot "" Then
SQLCmd_ALID2.ExecuteNonQuery()
End If
SQLcon.Close()
End If
任何想法我哪里出错了?提前致谢!
【问题讨论】:
您的数据库设计有缺陷。SONG_ID
列不属于Artist_DB
或Album_DB
。事实上,在现实世界中,同一首歌可能由多个艺术家演唱并出现在多张专辑中,而每个艺术家可能会演奏多首歌曲并制作多张专辑。我建议使用艺术家表、专辑表、歌曲表、艺术家和专辑之间的多对多桥接表,以及新表和歌曲表之间的多对多桥接表。
(继续)这将使您能够描述真实世界的情况,即同一首歌出现在两个不同艺术家的两张专辑中,或者两个艺术家一起创建专辑。
请开启 Option Strict。您可以在工具菜单 -> 选项 -> 项目和解决方案 -> VB 默认设置中找到此设置。这将使您避免在运行时出现错误。
If SID = "" Then SID += 1
什么是 SID?一个字符串?一个号码? Option Strict 会强制你将其声明为一种类型。
If Album IsNot "" Then
早在此之前就应该进行验证。
【参考方案1】:
If Album IsNot "" Then
SQLCmd2 = New SqlCommand("INSERT INTO ALBUM_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd2.Parameters.AddWithValue("@NAME", Album)
'SQLCmd2.Parameters.AddWithValue("@SONG_ID", SID)
End If
If Artist IsNot "" Then
SQLCmd3 = New SqlCommand("INSERT INTO ARTIST_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd3.Parameters.AddWithValue("@NAME", Artist)
'SQLCmd3.Parameters.AddWithValue("@SONG_ID", SID)
End If
您将这段代码的一半放在引号内。 替换为:
If Album IsNot "" Then
SQLCmd2 = New SqlCommand("INSERT INTO ALBUM_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd2.Parameters.AddWithValue("@NAME", Album)
SQLCmd2.Parameters.AddWithValue("@SONG_ID", SID)
End If
If Artist IsNot "" Then
SQLCmd3 = New SqlCommand("INSERT INTO ARTIST_DB (NAME) VALUES (@NAME)", SQLcon)
SQLCmd3.Parameters.AddWithValue("@NAME", Artist)
SQLCmd3.Parameters.AddWithValue("@SONG_ID", SID)
End If
如 cmets 中所述,以下行没有向插入语句添加任何内容,因为语句中没有 @SONG_ID
参数。这也可能导致问题。
SQLCmd3.Parameters.AddWithValue("@SONG_ID", SID)
SQLCmd2.Parameters.AddWithValue("@SONG_ID", SID)
【讨论】:
但是您正在添加不属于 Insert 语句的参数。以上是关于在 SQL/Vb.net 中的多个表之间填充主键/外键的主要内容,如果未能解决你的问题,请参考以下文章
MySQL存储过程---涉及多个表之间的关联关系,且各表中具有相同的字段,以主键id 为例,一定要使用 xx.id加以区分