use zzxdb2;
create table t_1(id int,nick nchar(12),birthday date);
create login zzxdb2 with password='zzxdb2' ,CHECK_POLICY=OFF;
create user zzxdb2 for login zzxdb2;
-- 当没有赋予权限的时候,zzxdb2可以登录SQL Server,但是看不到zzxdb2下面的TABLE
-- 所以,最后还需要赋予database user相应的权限,如下
exec sp_addrolemember 'db_owner', 'zzxdb2';
为什么容易混淆
通常的系统中只有用户的概念,权限系统都是基于用户。而SQL Server在其上新增了Login这一层,与其他的系统都不同。另外,在一般的客户端中,在需要登录的时候,通常都是使用”user name”/”password”作为登录认证的凭证,而不是”Login”/”password”,所以初学者通常容易混淆,例如微软的Mac客户端Azure Data Studio:
CREATE USER a_db_user_9zcloud WITHOUT LOGIN;
ALTER USER a_db_user_9zcloud WITH LOGIN='alogin';
-- 报错如下:
消息 33016,级别 16,状态 1,第 45 行
The user cannot be remapped to a login. Remapping can only be done for users that were mapped to Windows or SQL logins.
在给一个对象(主体)赋权的时候,可以通过按照细粒度(某个表的某种权限)方式进行,也可以直接将其加入到某个角色组,那么这个角色组对应的权限就都有了。例如,将login加入到”sysadmin”(fixed server role),那么就有了所有sysadmin角色组的权限,sysadmin可以理解是一个超级权限组,如果在该组中,那么访问对象时不需要检查该账号的权限;与sysadmin对应的一个权限是”CONTROL SERVER”,如果使用GRANT则可以使用这个权限。
另外,前文中偶尔会用到”主体”这个名称,英文对应SQL Server文档中的”Principals”,”主体”是SQL Server官方中文文档的翻译(参考)。可以理解为一个实体,或者前面对象的实例化或者实体,也就是说,某个具体的”server roles, logins, database roles, or users.” 都可以称作”Principals”。
在创建user的时候,如果没有显示的指定FOR LOGIN,没有指定WITHOUT LOGIN,那么该user将会被映射到同名的login上(还没有验证这一点,参考:If FOR LOGIN is omitted, the new database user will be mapped to the SQL Server login with the same name.)。
zzx@localhost % python3
Python 3.8.2 (default, Apr 8 2021, 23:19:18)
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
import pyodbc
# Some other example server values are
# server = 'localhost\sqlexpress' # for a named instance
# server = 'myserver,port' # to specify an alternate port
server = 'x.x.x.x'
# server = 'tcp:x.x.x.x,1433'
database = 'xxx'
username = 'xxx'
password = 'xxx'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
cursor = cnxn.cursor()
#Sample select query
cursor.execute("SELECT @@version;")
row = cursor.fetchone()
while row:
print(row[0])
row = cursor.fetchone()
一下子就跑通了? 有经验的开发者都知道,那当然不能这么顺利,是吧。首先,遇到如下报错:
Traceback (most recent call last):
File "mssqlremotessh.py", line 10, in <module>
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection (0) (SQLDriverConnect)')
# 注意:下面命令的IP和密码都被修改了
isql -v -k 'Driver={ODBC Driver 17 for SQL Server};Server=tcp:18.336.80.202,1433;Database=9zcloud;Uid=zzx;Pwd=********;'
[08001][Microsoft][ODBC Driver 17 for SQL Server]SSL Provider: [OpenSSL library could not be loaded, make sure OpenSSL 1.0 or 1.1 is installed]
[08001][Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection
[ISQL]ERROR: Could not SQLDriverConnect
这部分,在官网上有比较详细的说明:参考。这里简单说一下感受,目前,学习资料还不是很丰富,有一个200页的ppt,内容大致方向都涵盖了,但是实际考试试题是远超出ppt本身的内容的,ACP考试配套的还有一个视频学习课程,如果想顺利通过考试,认真学习视频是非常有必要的。另外,除了考试之外,还有一系列的动手试验,目前,这部分设计的都还比较简单,也都有step by step的引导,难度还不算高。