数据库的层次结构
SQLServer>多个服务器>多个数据库>多个table
连接数据库错误



win+R>services.msc



修改表后不允许保存



设置Id自增

让创建时间默认为现在时间
默认值或绑定写getdate()
为表批量设置创建时间
如果之前表里创建时间有NULL,先全部写入创建时间。
UPDATE UserTable
SET CreateTime=GETDATE()
WHERE CreateTime IS NULL
ALTER TABLE UserTable
ALTER COLUMN CreateTime DATETIME NOT NULL
删除已存在的存储过程
DROP PROCEDURE IF EXISTS XXX;
IF EXISTS (SELECT * FROM sysobjects WHERE name='XXX' AND type='P')
DROP PROCEDURE XXX
GO
type指定类型是存储过程。
增INSERT、删DELETE、改UPDATE、查SELECT
GO的意思
不是SQL语句,是SSMS专用的让SQL一段一段编译的。
SET NOCOUNT ON
让不再返回受影响的行数。
SELECT @@IDENTITY
获取你刚才插入数据,自动生成的 ID 号。
你数据库里一般都有一列:ID INT IDENTITY(1,1) PRIMARY KEY→ 自增主键,插入数据时不用你填,数据库自动给数字。
@@IDENTITY 就是拿到刚才那条数据的 ID 是多少。
设置存储过程执行到哪个数据库
在执行键左边选:

SELECT的作用
返回一张表。逗号分割输入它的列
char(n)、varchar和nvarchar
char(n):固定n个字节,没用完补空格。里面英文数字和中文字节数不一样。
var是长度可变的。
varchar:英文、数字1字节,汉字2字节。容易乱码。
nvarchar:各种语言一个字符都2字节。不容易乱码,多占空间。
sqlConnection.Open()错误

改成左边点开服务器资源管理器,连接成功后右下角拷贝连接字符串。
trust server certificate不支持

.NET Framework下这里不要有空格。
dataSet.Tables[0]是null

断点打太靠上了!!应该下面再写一行打断点。
Insert写字段名 → 可以只插部分字段 不写字段名 → 必须按顺序插全部字段
C#调用数据库的过程
建立SqlConnection>建立SqlCommand并和SqlConnection关联>
查询指令,建立SqlDataAdapter,和SqlCommand关联>建立DataSet,SqlDataAdapter.Fill填充数据>用Row和Column读取。
非查询指令,ExecuteNonQuery得到影响行数。
类的个数稍多,还可以。
编程语言调用数据库面对的情景
需要大量参数:连接字符串、表名、SQL语句或存储过程、SQL语句的参数(还包括参数名和参数值)。
而且需要参数的数量、类型不固定,select需要从0个(全查询)到任意多个条件,insert至少输入不能为Null的,如果想缺省还需要把参数名输入。
然后发现Select要返回数据表,增、删、改只返回影响的行数int,那么查封装一个函数,增删改封装一个。
然后因为要执行的SQL或存储过程极度灵活,应该封装一个输入指令的函数。那么还需要一些函数生成指令。
Entity
一个数据库表的一条数据在编程语言里对应的类。
从DataRow转换为Entity(基于反射、特性)
using System;
using System.Data;
using System.Reflection;
namespace LearnCSharp
{
public class AccountEntity
{
[DBName("Id")]
public int Id { get; set; }
[DBName("Status")]
public int Status { get; set; }
[DBName("UserName")]
public string UserName { get; set; }
[DBName("Password")]
public string Password { get; set; }
[DBName("Mobile")]
public string Mobile { get; set; }
[DBName("Email")]
public string Email { get; set; }
[DBName("Money")]
public int Money { get; set; }
[DBName("ChannelID")]
public int ChannelID { get; set; }
[DBName("LastServerID")]
public int LastServerID { get; set; }
[DBName("LastServerName")]
public string LastServerName { get; set; }
[DBName("LastServerTime")]
public DateTime LastServerTime { get; set; }
[DBName("LastRoleID")]
public int LastRoleID { get; set; }
[DBName("LastRoleName")]
public string LastRoleName { get; set; }
[DBName("LastRoleJobID")]
public int LastRoleJobID { get; set; }
[DBName("CreateTime")]
public DateTime CreateTime { get; set; }
[DBName("UpdateTime")]
public DateTime UpdateTime { get; set; }
public void SetData(DataRow row)
{
Type type = typeof(AccountEntity);
PropertyInfo[] propertyInfo=type.GetProperties();
foreach (var property in propertyInfo)
{
DBNameAttribute attribute = property.GetCustomAttribute<DBNameAttribute>(false);
if (attribute != null)
{
string colName = attribute.Name;
if (row.Table.Columns.Contains(colName))
{
object value = row[colName];
if (value != DBNull.Value)
{
property.SetValue(this, ConvertValue(value, property.PropertyType));
}
}
}
}
}
object ConvertValue(object value, Type targetType)
{
if (value == null)
return null;
Type underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;
return Convert.ChangeType(value, underlyingType);
}
}
}
join连表查询
左连:=左边的表都查出来,如果右边的表没有记录就显示NULL,也查出来。
select * from UserT
left join
UserScoreT
on UserT.UserName=UserSceneT.UserName
右连:=右边没有匹配的就不显示。
SQL Server身份验证登录



打开Services.msc>SQL Server重启。
由表得到创建它的SQL语句

ParameterDirection.Output和ParameterDirection.ReturnValue什么区别
Output
- 可以多个
- 类型任意(int、string、datetime 都行)
- 必须在存储过程声明
OUTPUT
ReturnValue
只能返回一个 int 数字,相当于存储过程的 exit code
C#的
sqlParameter.Direction = ParameterDirection.Output;
对应
@Id INT OUTPUT,
而
sqlParameter.Direction = ParameterDirection.ReturnValue;
在sql那边不写在参数列表,而是RETURN。
存储过程返回成功但是查询不到
用SQL执行存储过程没问题。
public MFReturnValue<int> Register(string username, string password,string channelId)
{
var ret = new MFReturnValue<int>();
using(SqlConnection connection=new SqlConnection(DBConn.UsersDB))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
List<AccountEntity> accountEntities =
GetListWithTran(TableName, "Id", $"UserName='{username}'", trans: transaction);
if (accountEntities == null|| accountEntities.Count==0)
{//用户名不存在
var entity=new AccountEntity();
entity.UserName = username;
entity.Password =MyTools.MD5(password);
entity.ChannelID =short.Parse( channelId);
entity.LastServerTime = DateTime.Now;
entity.CreateTime = DateTime.Now;
entity.UpdateTime = DateTime.Now;
MFReturnValue<object>ret1= Create(transaction, entity);
if (ret1.HasError)
{
ret.HasError = true;
ret.Message = ret1.Message;
transaction.Rollback();
System.Diagnostics.Debug.WriteLine($"注册出错!:{ret1.Message}");
}
else
{
System.Diagnostics.Debug.WriteLine($"注册成功:{ret1.Message}ID是{ret1.OutputValues["Id"]}");
ret.Value = (int)ret1.OutputValues["Id"];
}
}
else
{
ret.HasError = true;
ret.Message = "用户名已经存在";
}
}
public MFReturnValue<object> Create(SqlTransaction trans, T entity)
{
SqlParameter[] array = ValueParas(entity);
array[0].Direction = ParameterDirection.Output;
array[array.Length - 2].Direction = ParameterDirection.Output;
array[array.Length - 1].Direction = ParameterDirection.ReturnValue;
if (trans.IsNullOrEmpty())
{
MFSqlHelper.ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, "{0}_Create".FormatWith(TableName), array);
}
else
{
MFSqlHelper.ExecuteNonQuery(trans, CommandType.StoredProcedure, "{0}_Create".FormatWith(TableName), array);
}
int num = array[array.Length - 1].Value.ToInt();
MFReturnValue<object> mFReturnValue = new MFReturnValue<object>();
if (num < 0)
{
mFReturnValue.HasError = true;
}
else
{
mFReturnValue.HasError = false;
mFReturnValue.OutputValues["Id"] = array[0].Value.ToInt();
}
mFReturnValue.Message = array[array.Length - 2].Value.ObjectToString();
mFReturnValue.ReturnCode = num;
return mFReturnValue;
}
CREATE PROCEDURE [Account_Create]
(
@Id int Output,
@Status tinyint,
@UserName nvarchar(100),
@Password varchar(32),
@Mobile varchar(11),
@Email varchar(128),
@Money int,
@ChannelID smallint,
@LastServerID int,
@LastServerName nvarchar(40),
@LastServerTime datetime,
@LastRoleID int,
@LastRoleName nvarchar(40),
@LastRoleJobID int,
@CreateTime datetime,
@UpdateTime datetime,
@RetMsg nvarchar(255) Output
)
AS
BEGIN
BEGIN TRY
SET NOCOUNT ON;
--自定义逻辑开始
--自定义逻辑结
INSERT INTO Account
(Status,UserName,Password,Mobile,Email,Money,ChannelID,LastServerID,LastServerName,LastServerTime,LastRoleID,LastRoleName,LastRoleJobID,CreateTime,UpdateTime)
VALUES
(@Status,@UserName,@Password,@Mobile,@Email,@Money,@ChannelID,@LastServerID,@LastServerName,@LastServerTime,@LastRoleID,@LastRoleName,@LastRoleJobID,@CreateTime,@UpdateTime)
IF(@@ERROR = 0 AND @@ROWCOUNT > 0)
BEGIN
SET @Id = IDENT_CURRENT('Account')
SET @RetMsg = '添加成功';
RETURN 1;
END
ELSE
BEGIN
SET @RetMsg = '添加失败';
RETURN -2;
END
SET NOCOUNT OFF;
END TRY
BEGIN CATCH
SET @RetMsg = ERROR_MESSAGE();
RETURN -1;
END CATCH
END
GO
原因:事务没有提交,没有执行transaction.Commit();
Sql指令如何输入日期时间
C# DateTime转字符串需要加单引号:
DATE [Account] SET [Token]='e65da5ea-3ef5-4d25-b803-1c749ed145f6',
[ExpireTime]=2026/4/29 20:26:28 WHERE [Id]=1016
连接字符串
是一个ini格式的字符串,也就是用=连接键和值,;隔开字段。一个数据库连接字符串是这样
Data Source=.;
Initial Catalog=UsersDB;
Persist Security Info=True;
User ID=sa;
Password=XXXXXX
Data Source指定服务器名称,Initial Catalog指定数据库名称。


412

被折叠的 条评论
为什么被折叠?



