sql server数据库如何存储数组,int[]float[]double[]数组存储到数据库方法
原文地址:https://www.zhaimaojun.top/Note/5475296
将数组存储到数据库的方法
方法一:
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类型的数组很有可能就会包含逗号,所以,需要用一个确保不会出现在item中的符号来作为每个元素的分隔符,这样才能在下次读取数据后能重新分割,分开每个数组成员而不会出错!
}
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(二进制)形式存储的,不管是手机还是电脑,只不过数据的意义有所不同。
一般来说,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之后等长,如果不等长,反序列化时会造成困难,当然,也不是不行,在这部分代码中不行,下面还有一种方法,用于介绍不等长string的存储。
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;他们都是int,所以转化成byte后都是4个byte。(4个byte就不要抬杠了,如果非要抬杠,请自己换成sizeof(int)去计算长度)再比如,int a=9;double b = 9;他们是不同的数据类型,转化后a的长度是4,而b的长度是8,他们是不一样的!
}
在看反序列化过程:(将数据库中取出来的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[]进行存储的,没有写对其他类型的比如对象的属性变量等进行存储的,如果想要将某个对象进行存储,其实这个方法进行一定的变化就可以了,利用反射,获取对象的属性和变量,就可以进行存储了。代码就不贴了,如果有人想要就直接联系我。一般没几个人想要的。
sql server数据库如何存储数组,int[]float[]double[]数组存储到数据库方法的更多相关文章
- 在SQL Server 2014下面使用的SQL2000的Northwind和Pubs示例数据库
在SQL Server 2014下面使用的SQL2000的Northwind和Pubs示例数据库 http://files.cnblogs.com/files/lxzhangying/SQl2000S ...
- 02Microsoft SQL Server 安装,卸载,系统服务,系统组件及系统数据库
Microsoft SQL Server 安装,卸载,系统服务,系统组件及系统数据库 1. Microsoft SQL Server 安装 通过单击下拉框,选择浏览,然后在Active Directo ...
- SQL Server 无法在服务器上访问指定的路径或文件解决方法
SQL Server 无法在服务器上访问指定的路径或文件解决方法 在SQL Server附加数据库或备份数据库时出现:无法在服务器上访问指定的路径或文件. 请确保您具有必需的安全权限且该路径或文件存在 ...
- C 语言实例 - 计算 int, float, double 和 char 字节大小
C 语言实例 - 计算 int, float, double 和 char 字节大小 C 语言实例 C 语言实例 使用 sizeof 操作符计算int, float, double 和 char四种变 ...
- 关于c中 int, float, double转换中存在的精度损失问题
先看一段代码实验: #include<limits> #include<iostream> using namespace std; int main() { unsigned ...
- C++中将string类型转换为int, float, double类型 主要通过以下几种方式:
C++中将string类型转换为int, float, double类型 主要通过以下几种方式: # 方法一: 使用stringstream stringstream在int或float类型转换为 ...
- QT中QString 与 int float double 等类型的相互转换
Qt中 int ,float ,double转换为QString 有两种方法 1.使用 QString::number(); 如: long a = 63; QString s = QString:: ...
- [C++] string与int, float, double相互转换
参考:http://blog.csdn.net/candadition/article/details/7342380 将string类型转换为int, float, double类型 主要通过以下几 ...
- SQL Server性能优化(9)聚集索引的存储结构
一.索引的概念和分类 索引的概念大家都知道,日常开发中我们也会使用常见的聚集索引.非聚集索引.但是除了这两者以外,sqlserver中还提供其他的索引,如: a. 唯一索引:不包含重复键的索引,聚集索 ...
随机推荐
- windows10使用wireshark抓取本机请求包
1.管理员运行cmd 右键左下角windows图标,管理员运行Windows PowerShell 2.输入ipconfg查看本机ip和网关ip 3.执行命令 route add 本机ip mask ...
- simpholders 官方网址 https://www.simpholders.com/
SimPholders可让你快速直接地访问iPhone模拟器应用的app文档.你可以通过SimPholders找到数据库文件.永久存储以及缓存,它是一个非常实用的app debug工具,同时还可以离线 ...
- Linux开机显示模式切换
修改vim /etc/inittab 默认为5-图形界面模式,改为3-多用户模式即可 # Default runlevel. The runlevels used are: # 0 - halt (D ...
- Ansible之playbook剧本
Ansible之playbook剧本 目录 Ansible之playbook剧本 1. playbook的组成 2. 剧本示例test1 2.1 剧本制作 2.2 准备http.conf 2.3 运行 ...
- JAVA String介绍、常量池及String、StringBuilder和StringBuffer得区别. 以及8种基本类型的包装类和常量池得简单介绍
一.概述 String是代表字符串的类,本身是一个最终类,使用final修饰,不能被继承. 二.定义方式 方式一:直接赋值法 String str1 = "hello"; 方式 ...
- 面试官:谈谈你对IO流和NIO的理解
一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...
- redis(一)-----初识redis
Redis是一种基于键值对(key-value)的NoSQL数据库 因为Redis会将所有数据都存放在内存 中,所以它的读写性能非常惊人.不仅如此,Redis还可以将内存的数据利 用快照和日志的形式保 ...
- 用 Python 简单生成 WAV 波形声音文件
Python 简单生成 WAV 波形声音文件 让机器发出声响,本身就是一件充满魔法的事情.有没有想过,用一段简单的代码,生成一个最简单的声音呢?Python 这门脚本语言的库十分丰富,借助于其中的三个 ...
- 使用.rmp文件在redhat7.9安装oracle19c
19c开始,oracle提供了rmp安装包.感觉安装更方便一些了.记录一次测试环境安装. 1,创建交换空间 2,下载oracle 19c必要文件(oracle官网下载需要注册帐号,可以用迅雷下载后再上 ...
- vmstat监视内存的使用情况
vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可实时动态监视操作系统的虚拟内存.进程.CPU活动. vmstat的语法 vmstat [-V] [-n] [ ...