sqlserver数据库如何存储数组,int[]float[]double[]数组存储到数据库⽅法
将数组存储到数据库的⽅法
(本⼈平时同csharp编写代码,所以本⽂中代码都是csharp代码,有些地⽅java和csharp有所不同,⽂中会有提⽰)
⽅法⼀:
现在的电脑或者⼿机代码运⾏速度已经相当快了,⽽且各种语⾔,尤其是python,csharp,java等解析类语⾔的运⾏效率也⼤⼤提升,所以对字符串的操作很
简单快速了,所以很多⼈都喜欢将数据作为字符串进⾏操作。本⽅法就是将数组拼接后存储到数据库。基本的代码逻辑如下:
var source = new int[100];//new double[100];//new string[100];//等等各种类型的数组
var result = string.Empty;//最后要存储到数据库中的字符串
foreach(var item in source){
    result += item + ",";//这⾥要注意,⼀般都⽤,号,当然不限于,号,但是要注意,这个符号不能出现在item中,⼀般情况下,int,dobule,float,等等数组元素tostring之后都不会出现,号,但是string类型的数组很有可能就会包含逗号,所}
new SqlCommand("insert into XX(XX) value(" + result + ")",new SqlConnection("XX")).ExectueNoQuery();//将字符串类型的数据插⼊数据库
当需要将数据读取出来时(反序列化):
var sourcestring = "XXX,XXX,XXX,XXX";//从数据库读出的数据
var sourcedatas = sourcestring.Split(',');//当初⽤了什么符号拼接的就⽤什么符号分割!
var result = new int[sourcedatas.Lenth];//new double[];//new string[];//等等你当初存进去时的数组类型
for(int i = 0;i < sourcedatas.Lenth;i++){    if(string.IsNullOrEmpty(sourcedatas[i])) continue;
result[i] = int.TryParse(sourcedatas[i], out var v) ? v : default;//double.TryParse//按照当初存进去时的数据类型反向解析出原始数据!如果是string类型的,这个for循环不必要,sourcedatas就是result。
}
此⽅法的优缺点:
易读,数据库管理员查库的时候可以直观的看到数据内容,因为都是string,直接可以显⽰,⽽且对于很⼩的标号,⽐如999以下的标号存储来说,每个标号加⼀个分隔符都是2-
4字符,占⽤空间还是⽐较少的。缺点当然也很明显,对于string数组,分隔符不好取,对于double,long类型的数组,如果数据量很⼤时,就⾮常浪费空间,因为每个元素可能
要占⽤⼗多个字符。
⽅法⼆:
在这个⽅法之前先讲⼀下数据库中的⼀种数据类型:binary/varbinary:
这是⼀种将数据按照8bit直接进⾏存储的数据类型,数据内容不限制,可以是任何形式的数据。最⼤空间为8000*8bit。
如果对数据有所了解的同学应该知道,计算机中的所有数据都是binary(⼆进制)形式存储的,不管是⼿机还是电脑,只不过数据的意义有所不同。
java连接sqlserver数据库
⼀般来说,1bit就是1个⼆进制,8bit就是8个⼆进制,常常我们将8个⼆进制⽤byte表⽰⼀个字符,16个⼆进制⽤short表⽰,32个⼆进制⽤int表⽰,64个⼆进制⽤long表⽰,当然
这是整形的情况,还有float,是32bit来表⽰⼀个float数,⽤64bit来表⽰double,等等,这些其实都是计算机的基本知识。
⽽数组,他其实就是连续存放的⼀堆数据,只不过给他进⾏了按⼤⼩的分组⽽已。⽐如,int[8];他的⼤⼩其实就是8个int,也就是8*4个byte,也就是8*4*8个bit,所以我们要把
这些数据存储到数据库中,其实基本上就是直接内存拷贝就可以了,但是数据库他不⽀持内存拷贝啊~~
数据库也没有int[]这种数据类型啊,那怎么办呢,其实很简单,将int[]转化成byte[],再传递给数据库就可以了,数据库中的数据类型binary(8000)/varbinary(8000)就是为此⽽⽣
的。
但是这⾥需要考虑⼀个历史遗留问题:⼤⼩端模式问题,不同的操作系统中对数据保存时,⼤⼩端可能是不同的,不能盲⽬的⽤位移操作和强制类型转换可能导致数据错误的情
况,即:int a = 888;byte[] b = new byte[2];b[0] = (byte)(a>>8);b[1] = (byte)a;这种序列化后反向序列化时,可能导致数据出错的情况。
还要考虑语⾔的问题,java环境中对数据的正负要求⾮常严格,如果代码不正确,序列化和反序列化时可能导致数据的异常,这就是考验程序员能⼒的时候了。
下⾯看序列化过程:(将int数组转为byte数组)
var values = new int[100];//new double[100];//new float[100];//⼀些基本的数组类型,但是不能为string,除⾮所有的string都在GetBytes之后等长,如果不等长,反序列化时会造成困难,当然,也不是不⾏,在这部分代码中不⾏,下⾯还有⼀种⽅法,var result = new byte[values.Length * 8];//byte类型的需要存储到数据库中的结果数据
for (int i = 0; i < values.Length; i++)
{
var bts = BitConverter.GetBytes(values[i]);//这⾥不同的数据类型他的长度是不⼀样的。需要注意
Array.Copy(bts, 0, gds, i * bts.Lenth, bts.Lenth);//这⾥的长度要注意,不是固定的8,应该⽤bts.Lenth为准!不同的数据类型转化为byte后长度是不同的!但是所有的相同数据类型的数据转化后的byte是相同的,⽐如:int a=9;int b=900999
}
在看反序列化过程:(将数据库中取出来的byte转化成int数组)
var soucedata= new byte[8000];//数据库中读取出来的binary类型的数据
var result = new int[soucedata.Length / sizeof(int)];//这⾥数据类型的就是当初存储时的原始类型,⼀般int的⼤⼩是4,如果不确定,可以⽤sizeof计算,不同的类型这⾥的类型是不同的
for (int i = 0; i < soucedata.Length; i++)
{
result[i] = BitConverter.ToInt(soucedata[i],i*sizeof(int));//这⾥就需要考虑⼤⼩端的问题,BitConverter默认是⼩端模式,你可以⾃⼰百度如何设置⼤⼩端。
}
此⽅法的优缺点:
对于不等长不规则的数组⽆能为⼒,数据的不直观,数据库管理者看到的都是⼀堆16进制的码,易读性差,⼏乎不可改错,但是,对⼤数据的存储效果相当可观,能⼤⼤降低存
储的数据量,⽽且⼏乎是将数据进⾏了内存拷贝,对于数据的使⽤来说提⾼了效率。
⽅法三:
这是基于⽅法⼆的⼀种扩展⽅法,针对⼀些不规则数组,⽐如string[];struct等,与⽅法⼆同样,都是使⽤数据库的binary/varbinary数据类型存储数据的,主要解决了⽅法⼆中数
据不能可变长度的问题。
下⾯看序列化过程:(不规则数租转化为byte数组)
var sourcedata = new string[]{ "ff", "aaaa", "dddddddddddd"};//不规则长度的字符串数组
var ms = new MemoryStream();//⽤到了⼀个流,便于操作byte
foreach(var item in sourcedata){
var bt = Encoding.Utf8.GetBytes(item);//这是⼀种字符的编码形式,编码⽅式决定了反序列化后看到的内容是不是乱码,所以很关键!⼀般⽹络上都⽤的utf-8编码,这种编码⽀持多国语⾔,但是只是⽀持常⽤的词,有些⽣僻词是不⽀持的,根据⾃    var lbt = BitConverter.GetBytes((int)bt.Lenth);//这⾥⽤4个字符来表⽰这个可变长度数组内容的长度,
ms.Write(lbt,0,lbt.Lenth);//先写⼊4字节的长度,
ms.Write(bt,0,bt.Lenth);//再写⼊对应长度的内容,
}
ms.Seek(0,SeekOrigin.Begin);//这⾥是必须的,为了让ms流回到起点,否则后⾯的toarray会返回0字节
var result = ms.ToArray();//这⾥就得到了要写⼊到数据库的所有内容,当然,这⾥注意,result的⼤⼩要在8000以内,否则存储不进去的。
再看反序列化过程:(byte数组还原为数组)
var sourcedata = new byte[8000];//从数据库中读出的原始数据
var resultlist = new List<string>();//将要转换为的不规则数据的类型的数组
var ms = new MemoryStream(sourcedata);
do{
var bt = new byte[sizeof(int)];
ms.Read(bt,0,bt.Lenth);
var l = BitConverter.ToInt(bt,0);//获取不规则数据的长度
bt = new byte[l];
ms.Read(bt,0,bt.Lenth);
resultlist.Add(Encoding.Utf8.GetString(bt));//这⾥要使⽤存⼊数据库时使⽤的编码形式去转化,否则得到的结果可能都是乱码
} while(ms.Position < ms.Lenth);
var result = resultlist.ToArray();//得到了之前的不规则数据
此⽅法的优缺点:
这种⽅法可以对批量的字符串数组进⾏存储,能够很好的将不规则不等长的数组进⾏存储,补⾜了⽅法⼆中的缺点。但是我写的列⼦是对string[]进⾏存储的,没有写对其他类型的⽐如对象的属性变量等进⾏存储的,如果想要将某个对象进⾏存储,其实这个⽅法进⾏⼀定的变化就可以了,利⽤反射,获取对象
的属性和变量,就可以进⾏存储了。代码就不贴了,如果有⼈想要就直接联系我。⼀般没⼏个⼈想要的。