When you are attaching the pdf/any media stream the below processors are getting executed.
<attachFile argsType="Sitecore.Pipelines.Attach.AttachArgs">
<processor mode="on" type="Sitecore.Pipelines.Attach.CheckSize,Sitecore.Kernel"/>
<processor mode="on" type="Sitecore.Pipelines.Attach.UpdatePath,Sitecore.Kernel"/>
<processor mode="on" type="Sitecore.Pipelines.Attach.Save,Sitecore.Kernel"/>
</attachFile>
UpdatePath processor checks "File Path" field of the media item and if it is empty/null then it attaches the file to the DB instead of File system i guess; regardless of "UploadAsFiles" setting true/false.
If you are using the "Versioned" templates [ex - /sitecore/templates/System/Media/Versioned/Pdf] and Workflow enabled then you may not see this scenario. Because your initial version will be having the "File Path" value and the "File Path" is not a shared field in versioned templates, so when you detach and attach the file in further versions [2/3/etc.] will be saved in file system.
If you are using the "Unversioned" templates [ex - /sitecore/templates/System/Media/Unversioned/Pdf]
(I guess by default this will be used when your
"Media.UploadAsVersionableByDefault" setting is false in your config
or you don't check the "Make uploaded media items versionable" while
uploading the file)
then the initial file upload stores the file in file system but the further detach and attach is getting stored in DB. Because the detach is clearing the "File Path" and it's a shared field in UnVersioned templates, so when attaching the file again is not updating the File Path.
As a workaround i guess we can just attach the file without detaching it. [I don't see any issues attaching the file without detaching it]. But when we create a media item using any template [ex - /sitecore/templates/System/Media/Unversioned/Pdf] instead of upload as a file and try to attach the file in media field then that is not getting saved in DB. [even if "UploadAsFiles" as "True"]
Not sure whether the workaround makes sense for requirement, you can even consider replacing the default attach processors or inject your custom code but I would recommend you to reach out to Sitecore to check whether they have a patch/fix for this.