送大家以下 java 学习材料,文末有支付形式
之所以有这个题目,我既不是故意吸引眼球,也不想在本文对存储过程进行教科书般阐述。最近我的项目中遇到的存储过程问题,让我想起了去年在武汉出差时一位共事的提问:
我感觉存储过程挺好用的,为什么你不倡议用?
过后我好似胸有万言,但究竟没用一个切实的例子答复共事,只是从论断上大侃一通,代码绝对于 SQL,复用、扩大、通用性都要更强。想必共事并不服气。
当初想来,我最近正碰到的问题,算是一个能够答复共事的例子吧。
最近我的项目中有个新需要,须要校验一个用户是否有 Job,Certification,Disclosure 这三个业务数据。
翻看了代码发现,零碎的用户集体页面的 C# 代码调用了三个存储过程,去抓取用户的 Job,Certification,Disclosure 数据。
我的新需要,天然须要复用这三个存储过程,否则:
若每一处都写一次抓取数据的业务逻辑代码,若业务逻辑发生变化,难以追究和保护所有读取 Job,Certification,Disclosure 的 SQL。
如果我在 C# 代码中调用这已有的三个存储过程,事件本该十分快就能完结。我也是这么做的。
但 code reviewer 认为,我的需要中,并不需要 Job,Certification,Disclosure 这三个业务对象的数据。我只是须要给定用户 \_是否 \_有 Job,Certification,Disclosure 而已。所以我应将是否有无 Job,Certification,Disclosure 的判断逻辑写在数据库,最终通过网络从数据库传到 web 服务器的仅是 true 或 false,节俭网络流量,这样最好不过了。
也对。除开网络性能,从接口设计的角度讲,接口的传入和返回值,都应是你自身须要的数据,不应带有大量不须要或者须要 caller 去预处理的数据。从接口语义表白就可知调用的目标,这样代码可读性也会有大大提高。
那就入手改。但没想到的是问题来了。
为了讲述问题,我简化代码,假如零碎现有的存储过程如下:
`CREATE PROCEDURE [dbo].[GetJobs]`
`(`
`@PersonId int,`
`@OrganizaitionId int`
`)`
`AS`
`BEGIN`
`SELECT JobId,JobName,JobType FROM Job WHERE PersonId = @PersonId AND OrganizaitionId = @OrganizaitionId`
`END`
我在新的存储过程中调用它,我须要取得该 person 的 jobs 的数量,即 GetJobs
返回后果集的 count。
为了实现这一目标,首先想到的是应用长期表,将返回后果集存入长期表,再对其进行 count(*)
的计数操作:
`CREATE PROCEDURE [dbo].[MyProc]`
`(`
`@PersonId int,`
`@OrganizaitionId int,`
`)`
`AS`
`BEGIN`
`CREATE TABLE #Temp(`
`PersonId int,`
`OrganizaitionId int`
`)`
`INSERT INTO #Temp EXEC dbo.GetJobs`
`@PersonId = @PersonId,`
`@ParentOrgId = @ParentOrgId`
`SELECT COUNT(*) FROM #Temp`
`END`
这种方法简略无效,但它存在重大的保护问题。将来如果被调用的存储过程的返回后果集字段有变动,那么 MyProc
中的长期表构造也须要随之变动。这是令人难以承受的。
那么将 MyProc
中的 INSERT INTO 换为 SELECT INTO 呢?很遗憾,答案是不行。SQL 自身并不反对这种用法。
给现有存储过程 GetJobs
加output
参数?本例中因为 GetJobs 已被其余多处代码或 SQL scripts 调用,所以对现有现有存储过程进行改变会有不小危险。
我搜遍网络,一位 MS MVP 的大神的文章简直总结了所有存储过程之间传递数据的办法: How to Share Data between Stored Procedures。他在文章中也无可奈何地说道
Keep in mind that compared to languages such as C# and Java, Transact-SQL is poorly equipped for code reuse, why solutions in T‑SQL to reuse code are clumsier.
最终我没能找到一种称心的方法,无奈之下我在新写的存储过程中将查问 Jobs 的语句写一了次。
存储过程在很多场景时有其劣势,比方性能。但对于业务逻辑的通用办法,十分不举荐将其写在存储过程中,代码复用、扩大与客户端语言比,相差甚远。兴许究竟能实现,但代价与危险比客户端语言要高,得失相当。
天知道还有没有机会和那位前共事再探讨这一话题呢。