经过很长一段时间和很多错误的转弯后,我终于将我的代码上传到我的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;
}
for
和where
的变体,但我的尝试却非常失败。
注意:我正在为每个用户创建一个列,以便不将文件路径数限制为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是一种可怕的空间浪费。
答案 0 :(得分:1)
您的数据库表根本没有标准化。因此,对于不浪费具有许多空值的行的问题的答案是规范化表格设计。
您需要将表架构更改为只有3列:UploadId, UserId, FilePath
,其中UploadId
将是自动递增的主键。此外,您需要将INSERT查询更改为如下所示。 使用此设计,用户可以执行的上传次数没有限制,并且没有浪费空间。
UserId
与AcNo
相同,因此您可以根据需要更改此列名称。
每次用户第一次上传时,您都不需要使用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)
)