将值INSERT到列中的下一个NULL

时间:2016-01-11 23:27:36

标签: sql-server database

经过很长一段时间和很多错误的转弯后,我终于将我的代码上传到我的azure blob存储,在我的服务器上的数据库中创建一个数据库列,其中包含用户唯一的帐号,并将上传的文件路径放入该列供以后参考。好极了! :)

但是每次我将文件路径上传到数据库时,字符串都会保存在数据库的下一行中(如附图所示)。但我想将它保存在单个列的下一个空行中,忽略其他列可能有更多值。

我尝试过使用public Map<Long, StoreItemDTO> getItems(Long storeId) { // Get all item_ids for the store SelectHavingStep<Record1<Long>> where = this.ctx .select(STORE_ITEM.ID) .from(STORE_ITEM) .where(STORE_ITEM.STORE_ID.eq(storeId)) .groupBy(STORE_ITEM.ID); // Get all store_item_details according to the fetched item_ids TableLike<?> storeItemDetails = this.ctx .select( STORE_ITEM_DETAILS.ID, STORE_ITEM_DETAILS.STORE_ITEM_ID, STORE_ITEM_DETAILS.NAME, STORE_ITEM_DETAILS.DESCRIPTION, STORE_ITEM_DETAILS.STORE_LANGUAGE_ID ) .from(STORE_ITEM_DETAILS) .where(STORE_ITEM_DETAILS.STORE_ITEM_ID.in(where)) .asTable("storeItemDetails"); // Join the result and use final Field<Long> itemIdField = STORE_ITEM.ID.as("item_id"); Result<?> fetch = fetch = this.ctx .select( itemIdField, storeItemDetails.field(STORE_ITEM_DETAILS.ID), storeItemDetails.field(STORE_ITEM_DETAILS.NAME), storeItemDetails.field(STORE_ITEM_DETAILS.DESCRIPTION), storeItemDetails.field(STORE_ITEM_DETAILS.STORE_LANGUAGE_ID) ) .from(STORE_ITEM) .join(storeItemDetails) .on(storeItemDetails.field(STORE_ITEM_DETAILS.STORE_ITEM_ID).eq(STORE_ITEM.ID)) .fetch(); final Map<Long, StoreItemDTO> itemIdToItemMap = new HashMap<>(); fetch.intoGroups( record -> { Long itemDetailsId = record.getValue(STORE_ITEM_DETAILS.ID); // ... sake of compactness StoreItemDetailsDTO storeItemDetailsDto = new StoreItemDetailsDTO(); storeItemDetailsDto.setId(itemDetailsId); // ... sake of compactness Long itemId = record.getValue(itemIdField); StoreItemDTO storeItemDto = new StoreItemDTO(); storeItemDto.setId(itemId); storeItemDto.getItemDetailsTranslations().put(languageId, storeItemDetailsDto); StoreItemDTO itemDetailsList = itemIdToItemMap.get(itemId); if(itemDetailsList == null) { itemDetailsList = new StoreItemDTO(); itemIdToItemMap.put(itemId, itemDetailsList); } itemDetailsList.getItemDetailsTranslations().put(languageId, storeItemDetailsDto); return null; }); return itemIdToItemMap; } forwhere的变体,但我的尝试却非常失败。

注意:我正在为每个用户创建一个列,以便不将文件路径数限制为1024.

注意2:当我读到if时,这个问题可能是不必要的,但我仍然不喜欢浪费所有这些行的想法,只是为了简化服务器管理工​​作室和服务器对象浏览器的可读性。

任何想法如何避免这种情况?

我的代码:

使用用户唯一帐号创建列:

"...if you have more than 9,223,372,036,854,775,807 rows you would run into problems...(maximum size of a bigint) – Martin Smith"

将保存的文件路径插入用户列:

oSqlCommand.CommandText = "IF COL_LENGTH('User_Images','" + AcNo.Text + "') IS NULL BEGIN ALTER TABLE User_Images ADD [" + AcNo.Text + "] char(200) null END";

在下图中,我上传了以用户1登录的两个文件,然后我上传了以用户2登录的两个文件,然后以用户8登录了一个文件。用户2和用户的第1-4行中的NULL值8是一种可怕的空间浪费。

enter image description here

1 个答案:

答案 0 :(得分:1)

您的数据库表根本没有标准化。因此,对于不浪费具有许多空值的行的问题的答案是规范化表格设计。

您需要将表架构更改为只有3列:UploadId, UserId, FilePath,其中UploadId将是自动递增的主键。此外,您需要将INSERT查询更改为如下所示。 使用此设计,用户可以执行的上传次数没有限制,并且没有浪费空间。 UserIdAcNo相同,因此您可以根据需要更改此列名称。

每次用户第一次上传时,您都不需要使用ALTER TABLE将新列插入原始表的第一个查询。

新的INSERT查询

   oSqlCommand1.CommandText =  "INSERT INTO User_Images([UserId], [FilePath]) VALUES (" + AcNo.Text + ",'https://xxxx.xxxx.core.windows.net/container-" + AcNo.Text + "/" + fileName + "');"

如果您认为用户可能会完成大量上传,请使用bigint作为UploadId数据类型,否则请使用int。我使用了bigint,因此如果用户上传的内容过多,您就可以避免溢出错误。

表格创建脚本

CREATE TABLE dbo.User_Images
(
 UploadId bigint IDENTITY(1,1) PRIMARY KEY,
 UserId  bigint,
 FilePath  varchar(5000)
)